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?
While in browsers the global scope is the window object, in nodeJS the global scope of a module is the module itself, so when you define a variable in the global scope of your nodeJS module, it will be local to this module. You can read more about it in the NodeJS documentation where it says: global.
To set up a global variable, we need to create it on the global object. The global object is what gives us the scope of the entire project, rather than just the file (module) the variable was created in. In the code block below, we create a global variable called globalString and we give it a value.
Scripts running under Node. js have an object called global as their global object.
In order to use Node. js core or NPM modules, you first need to import it using require() function as shown below. var module = require('module_name'); As per above syntax, specify the module name in the require() function.
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)();
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.
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
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With