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

时间:2017-02-10 12:34:59

标签: javascript node.js

当我使用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:\eckovation\temp\demo.js:3:8)
at Object.<anonymous> (E:\eckovation\temp\demo.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)

任何人都能解释为什么会这样吗?

3 个答案:

答案 0 :(得分:2)

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

假设您正在尝试使用闭包捕获当前循环迭代值,您也可以使用let声明,而不是for块的范围,例如:

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

答案 1 :(得分:1)

节点是正确的,表明你setTimeout中传递了一项功能。 IIFE的返回值为undefined

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

如果您想将某个功能传递给setTimeout,您必须从IIFE实际return function

答案 2 :(得分:0)

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