更好地理解循环中的JavaScript闭包

Better understanding of JavaScript closure inside loops

本文关键字:JavaScript 闭包 循环 更好      更新时间:2023-09-26

我现在正在处理闭包问题,我需要一些关于该主题的帮助:使用此代码进行培训:

for (var i = 1; i <= 10; i++) {
    setTimeout(function(j) {
        console.log(j);
    }(i), 1000);
}

此解决方案超时一秒钟,然后按升序打印1-10(如预期)。现在,我希望它每秒打印一次j:

1(秒通过…)
2(秒通过…)
3(秒通过…)
等等。

如何在不改变循环形式的情况下实现这一点?

提前感谢

setTimeout期望函数能够执行。你需要返回一个函数,而且,由于你的setTimeout调用将一个接一个地发生,你需要延迟它们

for (var i = 1; i <= 10; i++) {
    setTimeout(function(j) {
        return function() {
            console.log(j);
        }
    }(i), 1000 * i); // Delay
}

jsFiddle

这不会改变循环的形成。尽管您的最佳解决方案是不使用for循环,而是使用链式setTimeout调用:

var i = 0;
function start() {
    setTimeout(function() {
        i++;
        console.log(i);
        // If we haven't reached our limit, start again
        if(i < 10) start();
    }, 1000);
}
start();

jsFiddle

感谢RGraham提供的解决方案:

for (var i = 1; i <= 10; i++)(function (j) {
     setTimeout(function () {
          console.log(j)
     }, 1000*j);
})(i);

除了RGraham的答案外,我还想指出,在学习javascript时,您应该尽量避免使用函数表达式,因为它们会使代码读起来很困惑。

以下是没有函数表达式的初始代码:

for (var i = 1; i <= 10; i++) {
    setTimeout(doSomething(i), 1000);
}
function doSomething(i) {
    console.log(i);
}

或者更清晰的表示:

for (var i = 1; i <= 10; i++) {
    var k = doSomething(i);
    // doSomething doesn't explicitly return anything, so k === undefined
    setTimeout(k, 1000);
}
function doSomething(i) {
    console.log(i);
}

此外,正如我在评论中提到的,您的问题实际上与您的关闭尝试无关,而是与Javascript中异步操作的工作方式有关。对异步操作进行排序最常用的方法是延续传递样式/回调和承诺。