2013-04-22 99 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); 

所以你把它包在其中立即執行和內部功能得到我的該次迭代的正確值的函數上下文。