1

我有一个代码: 演示 jsFiddle

which 循环 3 次,每次创建一个返回循环序列号的新函数。

我希望看到循环序列插入到数组:0、1 和 2。

a[i] = function() {
            return i;
        }

一切看起来都很正常但是当我尝试打印我得到的数组时

结果:

arr[0] is =>function () { return i; }
arr[1] is =>function () { return i; }
arr[2] is =>function () { return i; }

编码:

function f() {
    var a = [];
    var i;
    for (i = 0; i < 3; i++) {
        a[i] = function() {
            return i;
        }
    }
    return a;
}
var arr = f();

for (var index = 0; index < arr.length; index++) {
    document.write("<b>arr[" + index + "] is </b>=>" + arr[index] + "<br>");
}​

为什么我没有得到结果0、1 和 2。

很多谢谢。

4

3 回答 3

3

因为a[i]是一个函数,而不是函数的返回值。所以基本上你用三个函数体填充你的数组,所以当你检索它们中的任何一个时,你就会取回函数体。您可以尝试a[i].call()调用返回的函数,但每次调用都会得到 3,这与 Pointy 在评论中指出的一致。因为这是调用循环时的最后一个值,所以在循环停止之前 i 变成了 3

小提琴

于 2012-09-17T19:00:00.620 回答
1

我想我理解为什么您希望所有数组元素都返回i构造函数时的值。这并不是什么大的飞跃,但是这些功能中的每一个都共享一个范围。这些值没有链接到创建的函数,它是比“母亲”函数更有效的范围。在此范围内,有一个名为的变量i会递增,直到3. 如果你真的非常想使用闭包,你唯一能做的就是:

function f()
{
    var a = [];
    var i;
    for (i = 0; i < 3; i++)
    {
        a[i] = (function(currentI)
        {//create a separate scope, pass current value of i to it
            return function()
            {
                return currentI;
            }
        })(i);
    }
    return a;
}
var arr = f();
for (var index = 0; index < arr.length; index++)
{
    document.write("<b>arr[" + index + "] is </b>=>" + arr[index]() + "<br>");
}​

这会产生预期的结果,如您在此处所见

于 2012-09-17T19:09:42.007 回答
1

仅作记录,如果您真的想要一个包含三个函数的数组,其中每个函数返回的值与i创建函数时的值相同,您只需在i将函数分配给时传递一个副本a[i]

function f() {
    var a = [];
    var i;
    for (i = 0; i < 3; i++) {
        a[i] = (function(n) {
            return function() {
                return n;
            };
        }(i));
    }
    return a;
}

var arr = f();

for (var index = 0; index < arr.length; index++) {
    document.write("<b>arr[" + index + "]() is </b>=> " + arr[index]() + "<br>");
}​

输出:

arr[0]() 是 => 0
arr[1]() 是 => 1
arr[2]() 是 => 2

JSFiddle

于 2012-09-17T19:17:41.370 回答