kYuZz
kYuZz

Reputation: 1732

Binding of `this` in a setTimeout() callback in Node.js

In Node.js, inside a callback passed to setTimeout(), this seems to be bound to the timeoutObject returned by setTimeout() itself (both in strict mode and in non strict mode!):

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

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

This is not the case in the browser, where this is bound (as I would expect) to the global object window (or is undefined, in strict mode).

The documentation doesn't say anything about this non-standard behaviour.

Why is this?

Upvotes: 5

Views: 705

Answers (2)

zangw
zangw

Reputation: 48526

Here is one discussion this` binding incorrect for `setTimeouf(..)` and `setInterval(..). Which explains the question, there was even an attempt to fix it which was not accepted.

Here are some ideas as below

setTimeout binds the timer object to "this" object in the callback. First of all, in most cases, the execution environment in Node is a "module", so when

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

This is the difference between browser and node. Making reference to "window" object in browser is easy becasuse it is a global object. But in Node, setTimeout/setInterval does no way to get the "exports" object nor the execution environment of the module.


Regardless, there are advantages to the current way set*() works (though, granted it is undocumented but it is being used in the wild). For example:

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

Upvotes: 1

Lukas Liesis
Lukas Liesis

Reputation: 26413

Nodejs is not browser. "Standards" what you are talking about are for browsers. Read the docs:

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

To implement these 2 timing functions "this" should be binded to window object (not available in Nodejs) or worker object (not available in nodejs).

Nodejs has it's own global object, that might be good target in this case, but I think it's better to have this binded to this function, not some global object. Seems like developers from Nodejs thinks that way too.

It's not against the "standards" because standards has nothing about such environment, where window, navigation, location objects are not present.

Upvotes: 1

Related Questions