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

时间:2014-10-26 07:30:37

标签: javascript closures

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

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

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

  

1(第二次通过......)
  2(第二次通过......)
  3(第二次通过......)
  等。

如何在不改变循环形成的情况下实现这一目标?

提前致谢

3 个答案:

答案 0 :(得分: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

答案 1 :(得分:1)

感谢RGraham的解决方案:

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

答案 2 :(得分:1)

除了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中的工作方式。排序异步操作最常用的方法是继续传递样式/回调和承诺。