Reputation: 4864
I've been toying with node.js lately and I ran into a weird behavior about the usage of this
in the global scope of a module.
this
is bound to module.exports in the global scope:
console.log(this === exports); // -> true
But this
is bound to global in a method scope:
(function() { console.log(this === global); })(); // -> true
This also lead to this confusing behavior:
this.Foo = "Weird";
console.log(Foo); // -> throws undefined
(function() { this.Bar = "Weird"; })();
console.log(Bar); // -> "Weird"
I guess that the solution is to never use this
in the global scope and explicitly use extends
or global
instead, but is there a logic behind all this or is it a bug or limitation in node.js?
Upvotes: 10
Views: 290
Reputation: 9434
I don't know if this is the exact intention of Node.js team, but I would be surprised if it was not. Consider this example ran in the dev console of a browser (e.g. chrome):
var x = function(){console.log(this)}
a = {}
a.x = x
a.xx = function(){x()}
a.x()
>> Object
a.xx()
>> DOMWindow
x()
>> DOMWindow
As you can see executing a method without specifying its context sets the context to be the global one. In this case the DOMWindow object.
When you are inside a module your context is the module, but executing a method in it without specifying a context with .call or .apply or obj. will use the global context, global
, instead of the local one, module.exports
.
Upvotes: 1
Reputation: 76736
In working on a simple CommonJS modules implementation, I had to think about what to do with this
in the global scope of the module; it's not addressed by the spec.
I also set it up as the exports
object at first, because I thought that would be useful, but later found some code I needed to "modulize" that was using this
to get a handle to the global object, so I changed this
back to the global object to provide as close of an environment to "normal" as possible for module code.
We can only guess at why node is set up the way it is (or ask the author), but my guess is it was done simply because it seemed like a useful idea, similar to the way you can give the module
object an exports
property in node and have it reflected in the module's actual exports
(this behavior also isn't part of the spec, but doesn't go against it either).
As for the part of your question about this
referencing global
in functions, as the other answers explain, that's just the way this
works; it's not a node-specific behavior, it's a weird javascript behavior.
Upvotes: 1
Reputation: 235982
The "logic" behind that is, that the value of this
always depends on how a function is invoked.
In your case, you have a self-executing anonymous function, there, this
always references the global object (non strict mode) or undefined
(ES5 strict).
If you want to access the "outer" this
value, you could either store a reference before executing that function, like
var outerScope = this;
(function() { outerScope.Bar = "Weird"; })();
console.log(Foo); // -> throws undefined
or re- .bind()
the functions scope yourself, like
(function() { this.Bar = "Weird"; }).bind(this)();
Upvotes: 7