2013-04-22 100 views
0

尝试创建test.tgt中的函数,其功能与test.src中的函数相同,只是它们将具有上下文。无法创建javascript关闭

test.src.fn() => test.work.fn.call(context) 

这里是试验台

 
var fn1 = function() { console.log('fn1'); }; 
var fn2 = function() { console.log('fn2'); }; 
var context = { a: 1 }; 
var test = { 
    tgt: {}, 
    src: { one: fn1, two: fn2 }, 
    init: function() { 
    for(var i in test.src) { 
     test.tgt[i] = function(arg) { test.src[i].call(test.cxt,arg); }; 
    } 
    } 
} 
test.init(); 
test.src.one() => 'fn1' 
test.tgt.one() => 'fn2' ouch!! 

问题是,直到执行功能test.src[i]未评估。

如何在新创建的函数中获得“真实”test.src[i]

+0

可能重复[Javascript闭合内循环 - 简单实用的例子](http://stackoverflow.com/questions/750486/javascript-closure-inside-loops-simple-practical-example) – 2013-04-22 12:26:54

回答

1

您在init中创建的所有函数都有共享闭包,所以它们共享i变量,因此它总是最后一个。试试这个:

init: function() { 
    for(var i in test.src) { 
     (function(idx) { 
      test.tgt[idx] = function(arg) {test.src[idx].call(test.cxt,arg); }; 
     }(i)); 
    } 
} 
+0

“所以他们共享我变量,因此它总是最后的“ - 很好的规则!你有这方面的资料吗? – 2013-04-22 12:48:19

+0

@ccyoung:https://developer.mozilla.org/en-US/docs/JavaScript/Guide/Closures#Creating_closures_in_loops.3A_A_common_mistake – 2013-04-22 14:19:35

2

尝试创建一个封闭的循环的每个迭代:

var fn1 = function() { console.log('fn1'); }; 
var fn2 = function() { console.log('fn2'); }; 
var context = { a: 1 }; 
var test = { 
    tgt: {}, 
    src: { one: fn1, two: fn2 }, 
    init: function() { 
    for(var i in test.src) { 
     test.tgt[i] = (function(index){return function(arg) { test.src[index].call(test.cxt,arg); };}(i)); 
    } 
    } 
} 
test.init(); 
test.src.one() // => 'fn1' 
test.tgt.one() // => 'fn1' 
2

这是一个经典的Javascript问题。您认为在for循环的上下文中的i应该被捕获为创建函数时的值,但是它是i的最后一个值。为了避开这一点,你可以在本地捕获它,像这样:

test.tgt[i] = (function(local_i){ 
    return function(arg) { test.src[local_i].call(test.cxt,arg); }; 
})(i); 

所以你把它包在其中立即执行和内部功能得到我的该次迭代的正确值的函数上下文。