当索引是闭包的一部分时,如何创建索引?

时间:2017-04-02 03:11:14

标签: javascript closures

在下面的代码中,我对注释“here!”的行感到困惑:

var foo = [];
for(var i = 0; i < 10; i++){
    (function(){
     var y = i;
     foo[i] = function(){return y;} //here!
 })();
}

为什么“i”值正确地创建了“foo”的索引?最后当我们尝试查询它的值是10.那么,为什么我们不会有这样的东西:

foo的内容:foo [10] // 10(在这个数组中只有这个位置)

我知道我们对“i”有一个闭包,因为我们正在做一个与另一个范围相关的引用,但是我不明白为什么“foo”的索引是正确创建的,有一个闭包超过“i”变量。

3 个答案:

答案 0 :(得分:1)

它起作用的原因是你的内部函数是从循环内同步调用的。

发生常见问题 - 在嵌套函数中引用外部索引 - 当该函数被异步调用 时,或者至少之后 >循环已经完全执行,这不是你的情况。

出错的示例:

var foo = [];
for(var i = 0; i < 10; i++){
    setTimeout(function(){
        var y = i;
        foo[i] = function(){return y;} //here!
    }, 0);
}

答案 1 :(得分:0)

为什么i值会正确创建foo的索引:

在javascript中,列表只是下面的一个对象。在变量上使用[]访问器可创建从[]的内容到指定值的映射。您正在将键i映射到返回y的值的函数。

为什么foo的索引是正确创建的,对i变量有一个闭包:

您正在循环中存储对函数的引用。如果您要执行以下操作,我相信您将获得预期的结果:

foo[10]() // This will return 10.

<强>参考文献:

Insert into array at non-existent index

答案 2 :(得分:0)

我认为查看循环的单个迭代以了解正在发生的事情是有用的。

让我们说i = 3

您创建一个匿名函数并指定y = i,使y指向值3,即。之后y的值并不依赖i。然后设置foo[3] = function() {return y; // return 3。关键点是i更改不会更改y的值。

此处唯一相关的闭包是授予foo[i]访问y的权限,尽管外部匿名函数已完全执行并完成。

另请注意,每次迭代都会声明一个新的var y,该i指向{strong>仅 y中的值。因此,每个函数在单独的执行上下文中返回单独的y

与以下代码进行比较,该代码没有中间变量(例如代码中的i),因此i引用{{的实际值 1}}在封闭范围内 - 即10,循环结束后i的值

for(var i = 0; i < 10; i++){
    (function(){
     foo[i] = function(){return i;} 
 })();
}

foo[3] = 10; // as you expected for your code

下面的另一个例子与你的类似,并且具有相同的行为,外部匿名函数的参数保存内部函数被关闭的值。

for(var i = 0; i < 10; i++){
    (function(x){
     foo[i] = function(){return x;}
 })(i); // notice that we pass i in here
}

foo[3] = 3;