【问题标题】:Immediately-Invoked setTimeOut expression立即调用的 setTimeOut 表达式
【发布时间】:2016-06-13 18:32:11
【问题描述】:

在下面的代码中,我使用 IIFE 在循环的当前迭代期间立即执行闭包。

for(var i = 0; i < 3; i++) {
  console.log('Im in counter ' + i);
  (function() {
    var num = i;
    setTimeout(function() {
        console.log(num);
    },0);
  })();
};

上面的代码打印输出如下:
我在柜台 0
我在 1 号柜台
我在柜台 2
0
1
2

如果在当前迭代中立即调用闭包,则以下输出是预期的,而不是上面给出的实际输出。谁能解释在 for 循环中 IIFE 这种奇怪行为的原因?
我在柜台 0
0
我在 1 号柜台
1
我在柜台 2
2

【问题讨论】:

  • 您缺少setTimeout 的第二个参数。
  • setTimeout 将函数排入队列以在未来某个时间点运行。在0 的超时下,当前运行的代码/函数完成后将其排队。浏览器将完成该功能,可能会运行一些其他事件/代码然后运行您的超时。

标签: javascript closures iife


【解决方案1】:

将函数传递给setTimeout 会将其放入队列中。它会在以下情况下触发:

  • 时间(您没有指定时间,但有最短时间)已用完并且
  • 事件循环没有忙于运行另一个函数

所以你进入了循环。记录值。在 setTimeout 队列上放置一个函数。然后重复。

最终你会到达循环的尽头。函数结束。因此,很快计时器就会用完,setTimeout 函数就会执行。下一个可以。以此类推。

【讨论】:

  • 但即使不使用 IIFE 也会发生这种情况。不是吗?
  • @Prem — 是的,IIFE 的唯一区别是阻止 num 成为全局变量(但 num 毫无意义,因为您可以直接使用 i
【解决方案2】:

下面的答案是正确的。 setTimeout 函数会立即执行(您可以通过编写 setTimeout 的返回值来验证这一点,它是计时器的标识符)。无需使用循环,只需在每次执行您传递给 setTimeout 的函数时验证该值。看看这段代码:

  var num = 3;

function a(x) {
  setTimeout(function c() {
    console.log(x);
    x++;
    if (x<= num) a(x);
  },1000);
}

a(0);

a 以初始值 0 调用。这会设置超时以记录该值。在该函数中,如果数字小于 num 变量,它会再次调用自身。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-01-07
    • 1970-01-01
    • 2012-12-28
    • 2017-04-06
    • 1970-01-01
    • 2016-05-04
    • 2020-01-02
    • 1970-01-01
    相关资源
    最近更新 更多