如何在for循环中使用setInterval函数

hyl*_*aus 29 javascript closures for-loop setinterval

我正在尝试运行多个计时器,给出一个可变的项目列表.代码看起来像这样:

var list = Array(...);

for(var x in list){
    setInterval(function(){
        list[x] += 10;
        console.log(x + "=>" + list[x] + "\n");
    }, 5 * 1000);
}
Run Code Online (Sandbox Code Playgroud)

上述代码的问题在于,更新的唯一值是列表末尾的项目,乘以列表中的项目数.

任何人都可以提供解决方案和一些解释,所以我知道它为什么会这样做?

Lap*_*ple 39

var list = [1, 2, 3, 4, 5];

for (var i = 0, len = list.length; i < len; i += 1) {
    (function(i) {
        setInterval(function() {
            list[i] += 10;
            console.log(i + "=>" + list[i] + "\n");
        }, 5000)
    })(i);
}
Run Code Online (Sandbox Code Playgroud)

这是工作代码:

var list = [1, 2, 3, 4, 5];

for (var i = 0, len = list.length; i < len; i += 1) {
    (function(i) {
        setInterval(function() {
            list[i] += 10;
            console.log(i + "=>" + list[i] + "\n");
        }, 5000)
    })(i);
}
Run Code Online (Sandbox Code Playgroud)

这里索引i存储在匿名函数中,因此它不会被连续循环覆盖.setInterval代码中的函数仅保留对最后一个值的引用i.


I a*_*ica 38

所以,有一些事情:

  1. 最重要的是,您传递的回调函数setInterval()维护对每个特定迭代期间存在x的快照值的引用,而不是快照值x.因此,正如x循环中所改变的那样,它也在每个回调函数中更新.
  2. 此外,for...in还用于枚举对象属性,并且在数组上使用时可能会出现意外行为.
  3. 更重要的是,我怀疑你真的想要setTimeout()而不是setInterval().

您可以通过提供其他参数来将参数传递给回调函数setTimout():

var timeoutID = window.setTimeout(func, delay, [param1, param2, ...]);
Run Code Online (Sandbox Code Playgroud)

这是一个例子:

var list = [1,2,3,4];

for (var x = 0, ln = list.length; x < ln; x++) {
  setTimeout(function(y) {    
    console.log("%d => %d", y, list[y] += 10);
  }, x * 500, x); // we're passing x
}
Run Code Online (Sandbox Code Playgroud)

幸运的是,数字通过值而非参考传递.


小智 6

您可以将forEach和结合起来setTimeout以间隔遍历数组。

let modes = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
let interval = 1000; //one second
modes.forEach((mode, index) => {

  setTimeout(() => {
    console.log(mode)
  }, index * interval)
})
Run Code Online (Sandbox Code Playgroud)