我正在阅读一本javascript书,并在闭包时遇到了以下代码
function constFunc() {
var funcs = [];
for (var i = 0; i < 10; i++) {
funcs[i] = function () {
return i;
}
}
return funcs;
}
var f = constFunc();
f[5]();
输出不是5。 给出的解释是&#34;嵌套函数不会制作范围的私有副本&#34;。 如果有人能解释上述声明,我将不胜感激。
答案 0 :(得分:2)
当你调用constFunc
时,循环运行并为funcs
数组的每个元素分配一个函数。这些函数都返回i
的值,该值在循环的每次迭代中从0
更改为9
。
这意味着,constFunc
执行i
后,9
的值将为i
。当你调用数组中的一个函数时,它会返回9
的值,正如我们刚刚看到的那样i
。在循环的每次迭代中都没有捕获for (var i = 0; i < 10; i++) {
(function (i) {
funcs[i] = function () {
return i;
};
}(i));
}
的值。
你可以通过循环中的闭包来强制它被捕获:
i
在这种情况下,您将在循环的每次迭代中有效地创建一个与i
具有相同值的新变量。您可以在行动中看到here。
通过将i
传递给函数,您最终会复制它的值。因此,在第一次迭代0
上的值为i
。我们将该值传递给新函数(参数i
是与循环初始化器中声明的i
不同的变量),然后从数组函数返回该值。这样,每个数组函数都返回不同的 i
,而不是每个都返回相同的{{1}}。
答案 1 :(得分:2)
你为什么期望5的输出?因为在创建函数时,i
是5.现在,正如我们所看到的,输出不是5(但是,如果我没有错过任何内容,9)。那为什么呢?
创建函数时,不会评估闭包内的i
,但是当它运行时。现在,这就是你发表的声明发挥作用的地方:只有一个i
- 在constFunc
内创建的声明。所有关闭都适用于那个。在constFunc
si完成工作之后,我显然具有9的值(因为这是循环停止的地方)。所有闭包现在输出9。
一个更简单的例子:
function outer () {
var i = 0;
function inner () {
return i;
}
i = 99;
}
outer();
inner(); // <- return 99, not 0.
答案 2 :(得分:1)
这个循环:
for(var i=0;i<10;i++)
{
funcs[i]=function(){return i;}
}
由于关闭,内部函数你正在访问i的父级变量,完成循环之后将是10.因此在循环后调用这些函数时它将返回你的值为10的值。
您可以通过将变量作为参数传递来解决它,因为参数创建了变量的新副本,即使在循环完成时也保持其状态。
var myFunctions= [];
function createMyFunction(i) {
return function() {
console.log("My value: " + i);
};
}
for (var i = 0; i < 3; i++) {
myFunctions[i] = createMyFunction(i);
}
答案 3 :(得分:1)
有一个名为i
的变量。
有10个函数返回i
。
这些函数中的每一个都返回单个i
变量的当前值。