什么样的块在Javascript中创建闭包

时间:2014-10-30 20:02:16

标签: javascript closures

使用Javascript工作了这么长时间后,我仍然遇到关闭问题的问题!



(function() {
    var pages = ["one", "two", "three"];
    for (var index in pages) {
        var p = pages[index];
        setTimeout(function() { console.log(p); }, 500);
    }
})();




上述代码段打印onetwothree不应该吗? AFAIK p位于由for块创建的闭包内,并且应保持不变,以便每个setTimeout取出它们!那么为什么要打印三个three s?

4 个答案:

答案 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)
    }
}