这个问题在这里已经有答案了:

考虑以下 JavaScript 代码:

var a = [];

var f = function() {

    for (var i = 0; i < 3; i++) {
        a.push(function(){alert(i)});
    }
    for (var j = 0; j < 3; j++) {
        a[j]();
    }
};

警报打印了三次“3”。我想要不同的行为 - 在循环的每次迭代中生成一个打印 i 的当前值的函数。IE。3 个打印不同索引的函数。

有任何想法吗?

有帮助吗?

解决方案

创建一个接受的匿名函数 i 作为参数并返回某个函数:

for (var i = 0; i < 3; i++) {
    a.push((function(i) {
        return function() {
            alert(i);
        }
    })(i));
}

for (var j = 0; j < 3; j++) {
    a[j]();
}

或者做类似的事情:创建一个接受的匿名函数 i 作为参数将函数添加到数组中:

for (var i = 0; i < 3; i++) {
    (function(i) {
        a.push(function() {
            alert(i);
        });
    })(i);
}

for (var j = 0; j < 3; j++) {
    a[j]();
}

其他提示

另一种方法是使用 柯里化:

var a = [];
var f = function() {
    for (var i = 0; i < 3; i++) {
        a.push((function(a){alert(a);}).curry(i));
    }
    for (var j = 0; j < 3; j++) {
        a[j]();
    }
};

// curry implementation
Function.prototype.curry = function() {
  var fn = this, args = Array.prototype.slice.call(arguments);
  return function() {
    return fn.apply(this, args.concat(
      Array.prototype.slice.call(arguments)));
  };
};

检查上面的代码片段正在运行 这里.

var iterate = (function () {
    var i, j = [];
    for (i = 0; i < 3; i += 1) {
        j.push(i);
        alert(j[j.length - 1]);
    }
}());

您不需要闭包来仅仅输出一个值。但是,您的代码应该包含在面向对象的函数中。不必调用函数即可执行。

您可以将循环体放入匿名函数中:

var a = [];

for(var i = 0; i < 3; i++) (function(i) {
    a.push(function() { alert(i); });
})(i)

for(var j = 0; j < 3; j++) {
    a[j]();
}

通过创建该函数并将循环的“i”值作为参数传递,我们在循环体内创建了一个新的“i”变量,该变量本质上隐藏了外部“i”。现在,推入数组的闭包会看到新变量,该变量的值是在第一个循环中调用外部函数时设置的。如果我们在创建新变量时使用不同的名称,这可能会更清楚......这做了同样的事情:

var a = [];

for(var i = 0; i < 3; i++) (function(iNew) {
    a.push(function() { alert(iNew); });
})(i)

for(var j = 0; j < 3; j++) {
    a[j]();
}

“iNew”的值被分配为 0,然后是 1,然后是 2,因为该函数是由循环立即调用的。

函数(i){警报(i)

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top