在下面的代码中,我对注释“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”变量。
答案 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.
<强>参考文献:强>
答案 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;