2012-09-07 56 views
1

可能重複:
Javascript closure inside loops - simple practical example的Javascript不需要關閉行爲

我試圖代碼類似於這樣:

var funcs = []; 
for (var i=0; i<5 ; ++i) { 
    funcs[i]=function() { 
     alert(i); 
    }; 
} 

顯然,調用funcs[0]不會警報0與預期的一樣,只是因爲變量i被匿名函數捕獲,並且調用funcs[0..4]中的任何一個都會提醒'4'(最後一次迭代後的值爲i並被所有創建的函數共享)。

第一部作品圍繞在我腦海中是使用某種函數發生器:

var funcs = []; 
for (var i=0; i<5 ; ++i) { 
    funcs[i]=(function(cap) { 
     return function() {alert(cap)}; 
    })(i); 
} 

該做的伎倆,但似乎真的令人費解和難以閱讀。有沒有更好的方式來獲得預期的行爲,而不使用函數包裝?

+0

你不能在函數聲明後面使用'funcs [i] .i = i;'嗎? –

+1

無法重新創建(Chrome 21/Mac 10.7)http://jsfiddle.net/VDm5C/ –

+0

Nop,因爲在我正在處理的實際情況中,範圍設置爲調用函數funcs [i] .call(someObject,..)'。這將覆蓋'this',並且'this.i'將不可訪問。 – sitifensys

回答

2

.bind功能允許您預先綁定的附加參數綁定功能:

var funcs = []; 
for (var i=0; i<5 ; ++i) { 
    funcs[i]=function(i) { 
     alert(i); 
    }.bind(this, i); 
} 

這是一個ES5功能,所以應該從事的IE9 +,Chrome,Safari,Firefox:

+1

IE瀏覽器仍然不是一個真正的瀏覽器:p(只是拖動) – sitifensys

0

當您不想用這些匿名函數嵌入代碼時,解決方案是定義(命名的)嵌入狀態(i)和函數(在原型中)的類。這是更LOC但有時更具可讀性:

var funcs = []; 
function MyFunc(i) { 
    this.i=i; 
} 
MyFunc.prototype.doIt = function(){ 
    alert(this.i); 
}; 
for (var i=0; i<5 ; ++i) { 
    funcs[i]=new MyFunc(i); 
} 

funcs[2].doIt();​ 
2

您應該儘可能簡單地編寫它。我認爲這很容易理解,但很難閱讀。所以簡化它的一種方法是使用嵌套編碼風格。我不認爲這比現在簡單。

我建議是這樣的:

var funcs = []; 

for (var i = 0; i < 5; ++i) { 
    funcs[i] = (
     function (cap) { 
      return function() { alert(cap) }; 
     } 
    )(i); 
} 
1

恕我直言,命名函數往往優越,對性能和可讀性的原因。爲什麼不去做這樣的:

function foo (cap) { 
    return function() { alert(cap) }; 
} 

var funcs = []; 
for (var i=0; i<5 ; ++i) { 
    funcs[i]=foo(i); 
} 
+0

因爲你需要編寫一個沒有用在其他地方的頂級函數? – Jon

+2

喬恩:它不一定是頂級的,它只是在範圍內。 –

+0

當然,我的錯誤表達方式;假裝它不在那裏。它仍然不是理想的,它實際上是與例如創建類來模擬C++和C#等語言中的閉包。他們都專門添加了lambda表達式,因此您不必編寫這種「機器」代碼。 – Jon

0

試試這個:

var funcs = [0, 1, 2, 3, 4].map(function(i) { 
    return function() {alert(i);}; 
}); 

注:map不受IE8及以上suppoted,但有一個​​它。

+0

我幾乎寫了這樣的答案,但後來決定'[0,1,2,3,4,...]'不會縮放... – Alnitak

+0

@Alnitak我知道這種感覺,兄弟。我只是想展示一些不同的東西。這全部屬於一些數組生成算法。也許分裂字符串,或創建'Uint8Array',或其他... – MaxArt

+0

啊,現在_that_我_can_解決:'Array.range = function f(m,n,z){return m <= - n? (z = f(m,n),z.push(n),z):[]};' – Alnitak