为什么 IIFE 在 for 循环中的 setTimeout 在 nodejs 中的行为与浏览器的行为不同



当我使用 setTimeout 执行一个简单的 for 循环时,我发现这很有趣,它在我的浏览器中工作正常,但在节点环境中不起作用。

我的代码是

function run(times) {
 for (var i = 0; i < times; i++) {
   setTimeout((function(j) {
     console.log(j);
   })(i), i * 10 );
 }
}
run(7);

虽然此代码在浏览器中运行良好,但在节点环境中不起作用。 我收到错误!

timers.js:327
throw new TypeError('"callback" argument must be a function');
^
TypeError: "callback" argument must be a function
at exports.setTimeout (timers.js:327:11)
at countWithSetTimeout (E:eckovationtempdemo.js:3:8)
at Object.<anonymous> (E:eckovationtempdemo.js:9:1)
at Module._compile (module.js:570:32)
at Object.Module._extensions..js (module.js:579:10)
at Module.load (module.js:487:32)
at tryModuleLoad (module.js:446:12)
at Function.Module._load (module.js:438:3)
at Module.runMain (module.js:604:10)
at run (bootstrap_node.js:394:7)

谁能解释为什么会这样?

您不是为第一个参数传递函数,而是传递立即调用的函数的结果。在这种特殊情况下,函数没有显式return,所以默认返回值是undefined,这不是一个函数。

假设您尝试使用闭包来捕获当前循环迭代值,您也可以只使用 let 声明,该声明的作用域为 for 块,例如:

function run(times) {
  for (let i = 0; i < times; i++) {
    setTimeout(function() {
      console.log(i);
    }, i * 10 );
  }
}

Node 正确识别您没有setTimeout 中传递函数。IIFE 的返回值为 undefined

这里唯一的区别似乎是你的浏览器会悄悄地容忍setTimeout(undefined, n)而 Node 不会。

如果你想把一个函数传递给setTimeout,你必须从你的IIFE中return一个function

setTimeout需要一个回调作为第一个参数,在你的代码中发生的事情是浏览器忽略了这一点,只是在循环内执行函数并显示它,尝试增加时间(setTimeout的第二个参数(,即使在浏览器上它也不会有任何影响,函数将立即执行。正如其他节点所提到的.js正确识别这一点并抛出错误。

最新更新