setInterval(func)和setInterval(function(){func()}之间的区别是什么

时间:2015-07-23 19:57:29

标签: javascript node.js windows v8

我的前任老板有weird bug where when he used setInterval with a long delay interval

setInterval(func, 3000000 /*50 minutes*/);

Node.js崩溃。

func甚至可以是简单的console.log('something')

有人建议他在func附近包装一个匿名函数,它实际上解决了他的问题。

据我所知,至少在浏览器的javascript中它不应该有所作为甚至被认为是一种不好的做法。

之间的Node.js是否存在差异
  • setInterval(func, delay)
  • setInterval(function(){func()}, delay)

或者它是Node.js中的错误吗?

更新

Bug report on GitHub

2 个答案:

答案 0 :(得分:1)

直接解决您的问题:是的,存在差异。不在setInterval的功能中,而是在函数运行时将具有的范围。

情景1:

setInterval(function() {
  console.trace();
}, 3000000);

每隔50分钟,堆栈跟踪将打印到控制台。在这种情况下,因为函数console.trace已被直接调用,它将保持console的上下文。

情景2:

setInterval(console.trace, 3000000);

这将抛出一个错误,因为它将使用执行它的作用域的上下文调用,而不是console。要维护上下文,可以传递函数的绑定副本:

setInterval(console.trace.bind(console), 3000000);

看起来你的老板今天可以复制的问题似乎没有。因此,正如其他人所建议的那样,垃圾收集可能存在问题。但是,我更倾向于相信你的老板正在调用的函数取决于通过匿名函数维护的特定上下文,但在传递未绑定函数时会丢失。

答案 1 :(得分:0)

V8可能通过删除你在这里引用的任何函数作为“func”来进行幕后垃圾收集。这会使“func”指向无效的函数。

尝试使用以下参数运行节点:

node --expose-gc app.js

...然后在setInterval(func,10000)之后的代码中调用:

global.gc();

...将触发V8中的垃圾收集。由于我已将计时器降至十秒,您可以在不等一整个小时的情况下测试理论。

包装匿名函数调用完全有可能阻止垃圾收集从内存中删除实际函数。

请注意,您也可以从:

开始
 node --trace-gc app.js

...将通过V8记录垃圾收集。它可能告诉你一些有趣的东西。见https://groups.google.com/forum/#!topic/nodejs/gITsLR7Zkew