在IIFE中针对循环中的标准调用setTimeout()

时间:2018-04-03 08:52:46

标签: javascript loops closures iife

IIFE函数背后的逻辑和循环中setTimeout()背后的逻辑是什么? 有两个for

for (var i = 0; i < 10; i++) {
  // Standard
  setTimeout(function() {
    console.log("Standard" + i);
  }, 1000 * i);
}

for (var j = 0; j < 10; j++) {
  // IIFE
  (function(j) {
    setTimeout(function() {
      console.log("IIFE " + j);
    }, 1000 * j);
  })(j);
}

现在当我使用node.js运行时,我在10秒后得到了这个结果(每秒console.log()执行一次):

PowerShell

有人可以向我解释调用第一个函数和第二个函数之间的运行时逻辑差异吗?

特别是如果你能回答这些问题:

  • 为什么for中每天都会执行日志? (1000 * i | j被忽略)
  • 为什么i的值总是10?

提前谢谢。

[编辑] 我不明白为什么在forconsole.log()每秒都会被解雇,但超时秒1000 * i|j可能是一个可见的超时。

2 个答案:

答案 0 :(得分:1)

为什么日志每秒都执行一次? (1000 * i | j被忽略)

这是因为setTimeout()是一个异步函数。因此,在此步骤中不会阻止执行,而是使用给定的持续时间参数启动时钟并继续执行。传递持续时间后,将触发事件,并将回调添加到事件循环队列中,以便逐个执行。

为什么i的值总是10?

这是因为closure的概念。当第一个“标准”超时时,i到那个时间的值已经是10(那时所有setTimeout都被注册)。在IIFE的情况下,j是函数中的形式参数,其在每次迭代之后接收循环计数器变量值。此函数中包含的setTimeout使用此j

答案 1 :(得分:0)

在第一个版本中,setTimeout在触发时从父作用域引用变量i,但到那时它已经发生了变化。

在第二步中,您创建了一个带有j参数的新范围,该参数不是对父范围j变量的引用。因此,当setTimeout触发时,它不会改变。