可能重复:
Javascript closure inside loops - simple practical example
看过许多关于setTimeout
和闭包的帖子,但我仍然无法传递一个简单的for循环计数器。
for (i = 0; i < 5; i++) {
setTimeout(function () {
console.log(i);
}, Math.floor(Math.random() * 1000));
}
给出
5
5
5
5
5
想要
0
1
2
3
4
怎么了?
请不要火焰,我以为我理解setTimeout()
故事,但显然不是。
答案 0 :(得分:14)
您可以使用闭包来保持对循环中i
的当前值的引用:
for (i = 0; i < 5; i++) {
(function(i) {
setTimeout(function () {
console.log(i);
}, Math.floor(Math.random() * 1000));
})(i); //Pass current value into self-executing anonymous function
}
但是,由于您使用随机超时,因此不太可能按顺序打印数字(您可以使用i * 1000
来使数字按升序打印,相隔一秒)。
答案 1 :(得分:4)
您需要将i
传递给setTimeout
中使用的函数。到第一个方法执行时,i
已设置为5。
由于拨打Math.Random()
,您的超时时间可变,因此超时时间会有所不同,您将无法按照预期的顺序获取超时。
for (i = 0; i < 5; i++) {
(function(i) {
setTimeout(function () {
console.log(i);
}, 1000);
})(i);
}
将Math.floor(Math.random() * 1000)
更改为简单1000
可确保函数按您期望的顺序执行。
答案 2 :(得分:3)
您需要将“有趣”代码包装在关闭i
的函数中,并将其复制到局部变量中:
for (i = 0; i < 5; i++) {
(function() {
var j = i;
setTimeout(function () {
console.log(j);
}, Math.floor(Math.random() * 1000));
})();
}
“中间”函数调用强制将j
的值固定在调用函数的位置,因此在每个setTimeout
回调中j
的值不同。< / p>