1

可能重复:
循环内的 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);
}

这可以解决问题,但看起来确实令人费解且难以阅读。有没有更好的方法来获得预期的行为而不使用函数包装器?

4

5 回答 5

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 上运行:

于 2012-09-07T14:29:49.627 回答
2

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

我建议这样:

var funcs = [];

for (var i = 0; i < 5; ++i) {
    funcs[i] = (
        function (cap) {
            return function () { alert(cap) };
        }
    )(i);
}
于 2012-09-07T14:30:24.137 回答
1

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

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

var funcs = [];
for (var i=0; i<5 ; ++i) {
    funcs[i]=foo(i);
}
于 2012-09-07T14:31:11.800 回答
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();​
于 2012-09-07T14:26:43.490 回答
0

试试这个:

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

注意:mapIE8 和更早版本不支持,但有一个通用的 polyfill 。

于 2012-09-07T14:32:16.590 回答