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

IT技术 javascript for-loop closures setinterval
2021-02-27 07:50:15

我正在尝试在给定可变项目列表的情况下运行多个计时器。代码如下所示:

var list = Array(...);

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

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

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

6个回答

所以,有几点:

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

您可以通过向以下对象提供附加参数来将参数传递给您的回调函数setTimout()

var timeoutID = window.setTimeout(func, delay, [param1, param2, ...]);

数字将通过值而不是引用传递。下面是一个例子:

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
}

是的,我可以推荐阅读这篇文章:blog.morrisjohns.com/javascript_closures_for_dummies最重要的是,循环中的 setTimeout 无论如何可能不是他想要做的,因为所有回调将同时被触发,它们不会交错。
2021-04-25 07:50:15
OP 不需要“需要一个闭包”,恰恰相反——它对x有一个需要避免的闭包(你的答案实际上是这样做的)。不过,它保留了关闭列表
2021-05-05 07:50:15

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);
}

这是工作代码:

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);
}

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

优秀的解决方案!一个小提示:任何可以在循环中更改的内容都可以传递给匿名函数,而不仅仅是 index.html 。
2021-04-28 07:50:15

您不必在setInterval语句中使用 for 循环试试这个:

var list = Array(...);
var x = 0;

setInterval(function() {

    if (x < list.length;) {
        list[x] += 10;
        console.log(x+"=>"+list[x]);
    }

    else return;

    x++;
}, 5000);

您可以组合forEachsetTimeout以使用间隔循环遍历数组。

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)
})

我不知道如何使用 for 循环执行此操作,但此处的代码将按时间间隔打印出数组中的每个元素:

function displayText(str) {
   $('.demo').append($('<div>').text(str));
}
var i = 0;

var a = [12, 3, 45, 6, 7, 10];

function timedLoop() {
setTimeout(function () {
    displayText(a[i]);
    i++;
    if(i < a.length) {
        timedLoop();
    }
}, 2000)
}

timedLoop();

使用一些 jquery 在浏览器中显示它。