我正在阅读本网站以获取有关关闭的说明:blog.morrisjohns.com/javascript_closures_for_dummies.html
它有以下例子:
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]();
}
}
他们的笔记(正确地)指出:
行result.push(function() {alert(item +''+ list [i])}添加了一个 引用匿名函数 三次到结果数组。如果 你不是那么熟悉匿名 功能想到它: pointer = function(){alert(item +''+ list [i])}; result.push(指针);
请注意,运行示例时, “item3 undefined”被警告三 倍!这是因为就像 以前的例子,只有一个 关闭局部变量 buildList。当匿名 函数在线上调用 fnlistj;他们都使用相同的 单关,他们使用 i和项目的当前值 那一个闭包(我有一个值 因为循环已经完成, 和item的值为'item3')。
是否有一种“正确”的方式来获取javascript中的“预期”行为?
谢谢!
答案 0 :(得分:3)
result.push((function (jtem, j) {
return function() { alert(jtem + ' ' + list[j]); }
})(item, i));
您创建了一个匿名函数,它引入了一个新的变量范围。您立即执行该函数,传递变量,这些变量在新范围内成为新变量jtem
和j
,因此与item
和i
的“连接”是“破碎”。然后返回实际的函数,现在使用不同的变量(您可以保留名称i
和item
,我只是为了说明目的而更改它们。)
答案 1 :(得分:1)
是的,您将i的值赋给另一个变量,以便变量可以成为闭包的一部分。
function buildList(list) {
var result = [];
for (var i = 0; i < list.length; i++) {
var item = 'item' + list[i];
result.push(function(cItem, index){
return function(){ alert(cItem + ' ' + list[index]); }
}(item, i));
}
return result;
}
原因是JavaScript没有块范围,而是一个由函数捕获的词法范围。要解决这个问题,可以创建另一个函数,如上所示,从而将变量捕获到一个不受循环影响的新范围。