Javascript不需要的关闭行为

时间:2012-09-07 14:23:17

标签: javascript

  

可能重复:
  Javascript closure inside loops - simple practical example

我试图编写与此类似的代码:

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);
}

这就是诀窍,但看起来真的令人费解并且难以阅读。没有使用函数包装器,有没有更好的方法来获得预期的行为?

5 个答案:

答案 0 :(得分: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 :(得分:2)

你应该尽可能简单地写它。我觉得它很容易理解,但很难读懂。因此,简化它的一种方法是使用嵌套编码样式。我认为这不比现在简单得多。

我建议这样:

var funcs = [];

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

答案 2 :(得分:1)

恕我直言,出于性能和可读性的原因,命名函数通常都是优越的。为什么不这样做:

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

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

答案 3 :(得分: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();​

答案 4 :(得分:0)

试试这个:

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

注意:IE8及更早版本不支持map,但它有common polyfill