Javascript 闭包中如何引用局部变量?
我正在读一篇文章(),其中一个例子如下Javascript 闭包中如何引用局部变量?,javascript,loops,closures,Javascript,Loops,Closures,我正在读一篇文章(),其中一个例子如下 function buildList(list) { var result = []; for (var i = 0; i < list.length; i++) { var item = 'item' + list[i]; result.push( function() {alert(item + ' ' + list[i])} ); } return result; } function testList() {
function buildList(list) {
var result = [];
for (var i = 0; i < list.length; i++) {
var item = 'item' + list[i];
result.push( function() {alert(item + ' ' + list[i])} );
}
return result;
}
function testList() {
var fnlist = buildList([1,2,3]);
// using j only to help prevent confusion - could use i
for (var j = 0; j < fnlist.length; j++) {
fnlist[j]();
}
}
testList();
函数构建列表(列表){
var结果=[];
对于(变量i=0;i
调用testList时,会出现一个警告框,显示“item3 undefined”。文章有这样的解释:
在fnlist[j]()行调用匿名函数时代码>它们都使用相同的单个闭包,并且它们使用该闭包中i和item的当前值(其中i的值为3,因为循环已完成,item的值为'item3')
为什么项的值为“item3”?当我变成3时,for循环不是结束了吗?如果结束,项目不应该仍然是“项目2”吗?或者,当testList调用函数时,是否再次创建变量项?您已接近
为什么项的值为“item3”?当我变成3时,for循环不是结束了吗
对
如果它结束了,这个项目不应该仍然存在吗
“项目2”
没有。这个例子有点棘手。在循环的最后一次迭代中,i
是2,但它引用了list
数组的第三个元素,即3。换句话说,item==“item”+列表[2]==“item3”
或者,当testList调用函数时,是否再次创建变量项
不,你第一次几乎是对的。我想您刚刚错过了项[2]
的值为3。循环在我变为3时结束,但存储在闭包中并通过警报显示的“item”变量设置为
var item = 'item' + list[i];
文本“item”+列表[2]中的值。第三个列表项是3,因此文本是item3正如您所说,list
变量存储在closure中
实际上,您可以访问list
变量,但您正在尝试访问list[3]
。毕竟,i
变量也存储为闭包,当调用console.log
函数时,它的值为3。在执行以下操作之前,buildList中的for循环完成:
for (var j = 0; j < fnlist.length; j++) {
fnlist[j]();
}
我想你遗漏的一点是,list[I]
被低估了,因为I
是3,而list
只为0..2定义。是不是一个bug导致了比预期链接更多的文本?哇,太简单了。我怎么会错过呢?从零开始计算总是把我搞得一团糟。谢谢如果这是您理解javascript闭包的唯一障碍,请拍拍自己的背!我认为这个例子太复杂了。@J-P,谢谢你的回复。我现在明白了为什么它是未定义的,但我可以问一下为什么你们的例子是有效的。为什么现在要为fnlist中存储的每个函数创建一个新的闭包?在“result.push”调用中声明和调用的函数会创建自己的闭包。@Pointy,为什么创建自己的闭包?因为它是一个匿名函数?@Nick,它创建自己的闭包仅仅是因为它是一个函数。函数中的函数形成闭包。。。因此,在循环的每次迭代中,我们都会创建一个新的闭包,它将保留i
和item
@J-P的当前值,谢谢你。我现在明白了。谢谢你的帮助。
function buildList(list) {
var result = [];
for (var i = 0; i < list.length; i++) {
var item = 'item' + list[i];
result.push(
(function(item, i){
// Now we have our own "local" copies of `item` and `i`
return function() {
console.log(item + ' ' + list[i])
};
})(item, i)
);
}
return result;
}