2012-09-07 30 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