Javascript不需要的关闭行为

Javascript unwanted closure behavior

本文关键字:不需要 Javascript      更新时间:2023-09-26

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

这确实奏效了,但似乎真的很令人费解,很难阅读。有没有更好的方法可以在不使用函数包装的情况下获得预期的行为?

.bind函数允许您将附加参数预绑定到绑定函数:

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

这是一个ES5函数,因此应该适用于IE9+、Chrome、Safari、Firefox:

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

我建议这样做:

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

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

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

试试这个:

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

注意:map不受IE8及更早版本的支持,但它有一个常见的polyfill。

当你不想用那些匿名函数嵌入你的代码时,一个解决方案是定义(命名的)类嵌入状态(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();​