使用Javascript工作了这么长时间后,我仍然遇到关闭问题的问题!
(function() {
var pages = ["one", "two", "three"];
for (var index in pages) {
var p = pages[index];
setTimeout(function() { console.log(p); }, 500);
}
})();

上述代码段打印one
,two
和three
不应该吗? AFAIK p
位于由for
块创建的闭包内,并且应保持不变,以便每个setTimeout
取出它们!那么为什么要打印三个three
s?
答案 0 :(得分:4)
JavaScript具有功能范围,而不是块范围。因此,当您循环遍历数组时(P.S。不对数组使用for..in
),您将创建3个闭包。您创建的每个闭包都引用相同的 p
变量。因此,当超时最终运行时,它们将全部打印"three"
,因为它们都打印相同的 p
变量。
您需要为数组中的每个元素创建一个新范围。幸运的是,JavaScript有一个内置函数,.forEach
。
(function() {
var pages = ["one", "two", "three"];
pages.forEach(function(p){
setTimeout(function() { console.log(p); }, 500);
});
})();

当它运行时,它会为每个元素运行回调。运行该回调时,会为每个元素创建一个新范围,因此它可以正常工作。
答案 1 :(得分:4)
for
块不会创建闭包。在JavaScript中,只有函数创建范围并且是一个闭包。所以你可以像这样写代码:
(function() {
var pages = ["one", "two", "three"];
for (var index in pages) {
var p = pages[index];
(function (p) {
setTimeout(function() { console.log(p); }, 500);
}(p));
}
})();
答案 2 :(得分:0)
由于延迟,“p”在读取时被重置。将“p”发送给函数。
http://jsfiddle.net/RCzech/pkk4pe3q/
(function() {
var pages = ["one", "two", "three"];
for (var index in pages) {
var p = pages[index];
timeout(p);
}
})();
function timeout (p){
setTimeout(function() { console.log(p); }, 500)
};
答案 3 :(得分:0)
这个问题因为setTimeout
函数,所以需要实现在这种情况下将函数命名为函数记录器的函数的函数
(function () {
var pages = ["one", "two", "three"];
for (var index in pages) {
var p = pages[index];
setTimeout(logger(p), 500);
}
})();
function logger(p) {
return function () {
console.log(p)
}
}