在Node.js的setTimeout()callback中绑定`this`

在Node.js中,在传递给setTimeout()的callbacktimeoutObjectthis似乎是绑定到由setTimeout()本身(严格模式和非严格模式)返回的timeoutObject

 var timeoutObject = setTimeout(function () { console.log(this === timeoutObject); // true }, 0); var timeoutObject = setTimeout(function () { 'use strict'; console.log(this === timeoutObject); // true }, 0); 

浏览器中并不是这种情况,在全局对象window (或者是undefined ,在严格模式下) this是绑定的(就像我所期望的那样)。

文档没有说这个非标准的行为。

为什么是这样?

Nodejs不是浏览器。 “标准”你正在谈论的是浏览器。 阅读文档:

https://html.spec.whatwg.org/multipage/webappapis.html#dom-windowtimers-settimeout

为了实现这两个定时函数,“this”应该被绑定到窗口对象(在Nodejs中不可用)或工作对象(在nodejs中不可用)。

Nodejs有它自己的全局对象,在这种情况下可能是很好的目标,但是我认为最好把这个绑定到这个函数上,而不是一些全局对象。 似乎Nodejs的开发人员也这样认为。

这并不违背“标准”,因为标准对这种环境没有任何规定,窗口,导航,位置对象不存在。

这里有一个讨论this` binding incorrect for `setTimeouf(..)` and `setInterval(..) 。 这就解释了这个问题,甚至有人试图解决这个问题,而这个问题没有被接受。

这里有一些想法如下

setTimeout将定时器对象绑定到callback中的“this”对象。 首先,在大多数情况下,Node中的执行环境是一个“模块”,所以在什么时候

 var k=2; exports.k=3; console.log(k);//2 console.log(this.k);//3 

这是浏览器和节点的区别。 在浏览器中引用“窗口”对象很容易,因为它是一个全局对象。 但在Node中,setTimeout / setInterval没有办法获得“exports”对象,也没有获得模块的执行环境。


无论如何,目前的方式设置*()的作品(虽然,它是无证的,但它是野外使用)有优势。 例如:

 setInterval(function() { if (/* <condition> */) this.unref(); // do more stuff }, /* <n> */);