javascript关闭立即评估

时间:2009-09-12 01:03:43

标签: javascript loops closures scope

考虑以下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的当前值的函数。即3个打印不同索引的函数。

有什么想法吗?

5 个答案:

答案 0 :(得分:7)

创建一个匿名函数,该函数接受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]();
}

答案 1 :(得分:6)

另一种方法,使用currying

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

检查上面的代码段here

答案 2 :(得分:1)

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

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

答案 3 :(得分:0)

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

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,因为循环立即调用该函数。

答案 4 :(得分:-2)

功能(I){警报(I)