在Node.js的setTimeout()callback中绑定`this`
在Node.js中,在传递给setTimeout()
的callbacktimeoutObject
, this
似乎是绑定到由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> */);