问题描述
所以我已经在这里学到了很多关于闭包的知识。
但是我仍然找到一个我自己无法解释的例子:
function buildList(list){
var result = [];
for(var i = 0; i < list.length; i++) {
var item = "item: " + list[i] + " i's value: " + i; //i has the value of 2 here, but why?
result.push( function(){document.write(item + ", list[i]:" + list[i] + ", i's value in the anonymous function:" + i + "<br>")});
} //i = 3 here
return result;
}
function testList(){
var testTheList = buildList([1,2,3]);
for (var j = 0; j < testTheList.length; j++) {
testTheList[j]();
}
}
testList();
正如我期望的那样,当我执行testList()时应该为3。
但是结果是:
项目:3我的值:2,列表[i]:未定义,我在匿名函数中的值:3
项目:3我的值:2,列表[i]:未定义,我在匿名函数中的值:3
项目:3我的值:2,列表[i]:未定义,我在匿名函数中的值:3
为什么我要为var item => 2而我要在匿名函数=> 3中? 在我阅读时,闭包创建了新的执行环境,但是我不应该为闭包使用相同的值吗?
编辑
这不是的重复 ,我不知道如何创建新的执行环境。
我想知道为什么同一变量i(循环)的值在同一范围内不同?
1楼
当您将新函数添加到result列表中时,它会保留对item变量的引用,并且i计数。
在buildList函数内部的循环期间,您不会创建几个item变量,但是您会覆盖现有的变量,在buildList函数的item和i变量执行值的末尾看起来像这样:
- 3
- “项目:3我的价值:2”
并且list[i]是undefined因为您的列表长度是3,没有list[3]项。
因此,当您从testList的循环中调用匿名函数时,将testList运行您与item和i变量保留的值完全相同的值。
还要在循环中创建匿名函数不是最佳实践,我建议您像这样修改buildList函数:
function buildList(list) { var index = 0; return function () { if (index >= list.length) return var item = "item: " + list[index] + " i's value: " + index; document.body.innerHTML += [ item, ", list[i]:", list[index], ", i's value in the anonymous function:", index, "<br>" ].join('') index++ } } function testList() { var list = [1, 2, 3]; var testTheList = buildList(list); document.body.innerHTML = ''; for (var j = 0; j < list.length; j++) { testTheList(); } } testList();