Javascript setTimeout()-在具有随机延迟的for循环中

Javascript setTimeout()-在具有随机延迟的for循环中,javascript,closures,settimeout,Javascript,Closures,Settimeout,可能重复: 看到很多关于setTimeout和闭包的帖子,但我仍然无法传递一个简单的for循环计数器 for (i = 0; i < 5; i++) { setTimeout(function () { console.log(i); }, Math.floor(Math.random() * 1000)); } (i=0;i

可能重复:

看到很多关于
setTimeout
和闭包的帖子,但我仍然无法传递一个简单的for循环计数器

for (i = 0; i < 5; i++) {
  setTimeout(function () {
    console.log(i);
  }, Math.floor(Math.random() * 1000));
}
(i=0;i<5;i++)的
{
setTimeout(函数(){
控制台日志(i);
},Math.floor(Math.random()*1000));
}
给予

5
5
5
5
五,

想要

0
1
2
3
四,

怎么了?

请不要激动,我以为我已经理解了
setTimeout()
的故事,但显然没有。

您需要将
I
传递给
setTimeout
中使用的函数。在执行第一个方法时,
i
已设置为5

由于调用
Math.Random()
,您的超时是可变的,因此超时将不同,并且您不会按照预期的顺序获得它们

(i=0;i<5;i++)的
{
(职能(一){
setTimeout(函数(){
控制台日志(i);
}, 1000);
})(i) );
}
Math.floor(Math.random()*1000)
更改为简单的
1000
可以确保函数按照您期望的顺序执行。

您需要将“有趣的”代码包装到关闭
i
的函数中,并将其复制到局部变量中:

for (i = 0; i < 5; i++) {
  (function() {
    var j = i;
    setTimeout(function () {
      console.log(j);
    }, Math.floor(Math.random() * 1000));
  })();
}
(i=0;i<5;i++)的
{
(功能(){
var j=i;
setTimeout(函数(){
控制台日志(j);
},Math.floor(Math.random()*1000));
})();
}

“中间”函数调用强制将
j
的值固定在调用函数的点上,因此在每个
setTimeout
回调中
j
的值是不同的。

您可以使用闭包在循环中保留对
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=0;i<5;i++)的
{
(职能(一){
setTimeout(函数(){
控制台日志(i);
},Math.floor(Math.random()*1000));
})(i) ;//将当前值传递给自动执行的匿名函数
}​
但是,这不太可能按顺序打印数字,因为您使用了随机超时(您可以使用
i*1000
使数字按升序打印,间隔1秒)


这是一个。

也许这里的特殊性是
random()
不是吗?不是。你会在固定的超时时间内遇到同样的问题。昨天也问过同样的问题。请检查我没有看到这个,但是在
setTimeout
延迟中仍然没有随机性(我认为这是区别)不,问题是您正在循环中创建一个函数。无论是否涉及
setTimeout
,是否涉及随机超时,都是不相关的。是否有理由对函数参数重复使用名称“i”?我注意到@JamieDixon也做了同样的事情。对我来说,这掩盖了一个事实,即它们是完全独立的变量,使理解变得更加复杂。以您的JSFIDLE为例:@JeremyWiebe-不,没有理由,您可以使用任何您喜欢的标识符。我倾向于使用同一个名字,因为我觉得它更清晰,但每个都有自己的名字。
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
}​