这个问题已经在这里有一个答案:
- JavaScript的闭包内环路-简单实用的例子 43个回答
我有一些JavaScript代码的问题。
脚本
setTimeout(function() {
for (var i = 0; i < 5; i++) {
setTimeout(function() {
console.log(i);
}, i * 200);
}
}, 200);
输出
5,5,5,5,而不是5 1,2,3,4,5
我可以种明白为什么这是行不通的,但我想知道如果有人能向我解释发生了什么,为什么它不工作!
此外,这怎么能范围的问题被克服?
该setTimeout
回调函数是异步执行的,所有console.log
叫你做参考同i
的变量,并在它们被执行时,for循环已经结束 , i
有4个。
你可以换你内心setTimeout
接受一个参数,以便将其存储到所有的引用的函数调用里面i
正在重复的值,这样的事情:
setTimeout(function() {
for (var i = 0; i < 5; i++) {
(function (j) { // added a closure to store a reference to 'i' values
setTimeout(function() {
console.log(j);
}, j * 200);
})(i); // automatically call the function and pass the value
}
}, 200);
检查我的回答更多细节以下问题:
看看这个问题 。 它可以帮助你理解范围和封闭好,非常相似,你的问题。
你想创建一个包含变量“i”的封闭。 但封闭在一个函数结束时才创建。 因此,如果在创建for循环的功能,它们将不得不从最后一次迭代的值。
你可以用这样的修正:
var createFunction = function(index) {
return function() {
console.log(index);
}
};
for (var i = 0; i < 5; i++) {
setTimeout(createFunction(i), i * 200);
}
在那里你从另一个函数返回的功能。
可变i
存在于外部函数的范围。
它改变的循环运行。
内部函数引用它。
尝试是这样的:
var i_print_factory = function (value) {
return function () {
console.log(value);
};
};
var init_timers = function () {
for (var i = 0; i < 5; i++) {
setTimeout(i_print_factory(i), i * 200);
}
};
setTimeout(init_timers, 200);
因为你正在访问同一个变量i在设定的超时用到的所有功能。 setTimeout函数集火的毫秒数在今后的同一个线程中变量i的功能。 I值并不在函数复制功能所引用的实际变量i,当它被激发。 因为你已经通过父函数循环,直到I = 5和之前其他任何有机会火做到这一点,他们都显示为5。