javascript在1秒后打印一个值

时间:2014-02-03 14:18:52

标签: javascript for-loop firebug

我只想在1秒后打印出for循环中的值,但是当我在firebug中运行代码时,每次运行代码时都会打印出意外的值。不确定发生了什么。

for(var k=0; k<3; k++) {
setTimeout(function() { console.log(k); },1000);
}

我预计1秒后: 0 1 2

相反,我得到了这个: 3635 3

5 个答案:

答案 0 :(得分:2)

您需要在函数中包含k变量的副本,否则您的函数将引用k变量,在该变量之外,函数执行时的值为3:

for(var k=0; k<3; k++) {
  (function(k_copy) {
    setTimeout(function() { console.log(k_copy); },1000);
  })(k); // immediately execute
}

使用Function.prototype.bind替代方案:

for(var k=0; k<3; k++) {
  setTimeout(function(k_copy) { console.log(k_copy); }.bind(null,k),1000);
}

答案 1 :(得分:1)

您看到的第一个整数是从setTimeout返回的结果 它是您可以在.clearTimeout()

中使用的超时的数字指针

除此之外,你必须使用一个闭包来打印正确的值。

for(var k=0; k<3; k++) {
    (function(k) {
        setTimeout(function() {
            console.log(k);
        },1000);
    })(k);
}

答案 2 :(得分:1)

您看到的四位数字是setTimeout的返回值,这是numerical id,您可以在以后用它来取消计时器。

setTimeout方法将其参数设置为稍后调用 ,并立即继续当前函数。所以你的代码很快完成了for循环,调用了setTimeout三次。完成该循环后,k为3。

然后,一秒钟后,超时触发,并将k(3)记录到控制台。

我相信你只看到3输出一次的原因是setTimeout只会为给定的函数设置一个超时。你传递了三次完全相同的功能。我没有在documentation中看到这种行为,因此它可能是实现定义的。

我怀疑你想要的是在一秒钟之后打印k的三个不同值。要做到这一点,你实际上需要创建一个不同的变量,其值不会改变。您可以使用返回函数的额外函数来执行此操作:

var makefunc = function (k2) {
    return function() { console.log(k2); };
}
for(var k=0; k<3; k++) {
    setTimeout(makefunc(k),1000);
}

每次调用makefunc时,它都会在此处创建一个新变量(名为k2,但实际上,如果该变量名为k),这也会起作用。该变量保持活跃状态​​,直到console.log呼叫一秒钟后。

更简洁的写作方式:

for(var k=0; k<3; k++) {
    setTimeout(function(k) { return function() { console.log(k); }; }(k), 1000);
}

答案 3 :(得分:1)

我建议在异步JavaScript上查找一些资源,因为理解这将有助于这种情况。 JavaScript是单线程的,在调用回调函数之前会等待。想一想:

  1. K = 0;进入循环,调用setTimeout()这是一个异步函数;回调函数被放入队列,代码继续运行而不执行它。
  2. K = 1;下一次循环迭代,调用setTimeout();回调函数被放入队列,代码继续运行而不执行它。
  3. K = 2;下一次循环迭代,调用setTimeout();回调函数被放入队列,代码继续运行而不执行它。
  4. K = 3; k&lt; 3检查失败并且退出循环。
  5. 现在它返回并查看队列中是否有任何等待执行的内容,并找到所有回调函数。
  6. 逐个执行回调函数,当前值为k,即3。
  7. 理解这是JavaScript中的关键。正如其他人已经说过的那样,你需要将k的值传递给每个回调(闭包),以便在回调首次放入堆栈时访问该值。

    (其他答案的代码完美无缺):

    for(var k=0; k<3; k++) {
        (function(k) {
            setTimeout(function() {
                console.log(k);
            },1000);
        })(k);
    }
    

    对于3635和3686标识符,这实际上是我刚才从其他答案中学到的新东西!谢谢!

答案 4 :(得分:0)

3635和3686是setTimeout函数的标识符,它们用于在必要时清除超时。要打印0,1,2,请使用下一个代码

for(var k=0; k<3; k++) {
(function(k){
setTimeout(function() { console.log(k); },1000);
})(k);
}