setTimeout() - 用于随机延迟的for循环

时间:2012-04-20 07:49:06

标签: javascript closures settimeout

  

可能重复:
  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()故事,但显然不是。

3 个答案:

答案 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来使数字按升序打印,相隔一秒)。

这是working example

答案 1 :(得分:4)

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

由于拨打Math.Random(),您的超时时间可变,因此超时时间会有所不同,您将无法按照预期的顺序获取超时。

Here's a working example

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>