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

kYu*_*uZz 5 javascript node.js

在Node.js中,传递给的回调内部setTimeout(),this似乎绑定到自己timeoutObject返回的setTimeout()(在严格模式和非严格模式下!):

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

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

在浏览器中不是这种情况,它this被绑定(如我所料)到全局对象window(或者undefined在严格模式下).

该文档没有说明这种非标准行为.

为什么是这样?

zan*_*ngw 1

这是一个讨论this` binding incorrect for `setTimeouf(..)` and `setInterval(..)。这解释了这个问题,甚至有人尝试修复它,但没有被接受。

以下是一些想法

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

var k=2;
exports.k=3;
console.log(k);//2
console.log(this.k);//3
Run Code Online (Sandbox Code Playgroud)

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


无论如何,当前的 set*() 工作方式有其优点(尽管它没有文档记录,但它正在广泛使用)。例如:

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