qol*_*lin 57 javascript closures loops
我对这段代码感到非常困惑:
var closures = [];
function create() {
for (var i = 0; i < 5; i++) {
closures[i] = function() {
alert("i = " + i);
};
}
}
function run() {
for (var i = 0; i < 5; i++) {
closures[i]();
}
}
create();
run();
Run Code Online (Sandbox Code Playgroud)
根据我的理解,它应该打印0,1,2,3,4(这不是闭包的概念吗?).
而是打印5,5,5,5,5.
我试过Rhino和Firefox.
有人可以向我解释这种行为吗?Thx提前.
Chr*_*oph 60
通过添加额外的匿名函数修复了Jon的答案:
function create() {
for (var i = 0; i < 5; i++) {
closures[i] = (function(tmp) {
return function() {
alert("i = " + tmp);
};
})(i);
}
}
Run Code Online (Sandbox Code Playgroud)
解释是JavaScript的作用域是函数级的,而不是块级的,并且创建闭包只意味着封闭的作用域被添加到封闭函数的词法环境中.
循环终止后,函数级变量i具有值5,这就是内部函数"看到"的内容.
作为旁注:你应该注意不必要的函数对象创建,特别是在循环中; 这是低效的,如果涉及DOM对象,很容易创建循环引用,从而在Internet Explorer中引入内存泄漏.
我想这可能是你想要的:
var closures = [];
function createClosure(i) {
closures[i] = function() {
alert("i = " + i);
};
}
function create() {
for (var i = 0; i < 5; i++) {
createClosure(i);
}
}
Run Code Online (Sandbox Code Playgroud)
解决方案是让一个自动执行的lambda包装你的数组push.你也将i作为参数传递给那个lambda.自执行lambda中的i值将影响原始i的值,一切都将按预期工作:
function create() {
for (var i = 0; i < 5; i++) (function(i) {
closures[i] = function() {
alert("i = " + i);
};
})(i);
}
Run Code Online (Sandbox Code Playgroud)
另一种解决方案是创建另一个闭包,它捕获i的正确值并将其分配给另一个在最终lambda中"被捕获"的变量:
function create() {
for (var i = 0; i < 5; i++) (function() {
var x = i;
closures.push(function() {
alert("i = " + x);
});
})();
}
Run Code Online (Sandbox Code Playgroud)