I have a JavaScript file which is loaded by require
.
// loaded by require()
var a = this; // "this" is an empty object
this.anObject = {name:"An object"};
var aFunction = function() {
var innerThis = this; // "this" is node global object
};
aFunction();
(function(anyParameter){
console.log(anyParameter.anObject);
})(
this // "this" is same having anObject. Not "global"
);
My question is: this
in var a = this;
is an empty object whereas this
statements in functions are shadows of node.js global object. I know this
keyword is different in functions but I could not understand why first this
is not equal to global and this
in functions equals to global.
How does node.js inject global
to this
in function scopes, and why it does not inject it to the module scope?
Here's a few fundamental facts you must understand to clarify the situation:
In the top-level code in a Node module,
this
is equivalent tomodule.exports
. That's the empty object you see.When you use
this
inside of a function, the value ofthis
is determined anew before each and every execution of the function, and its value is determined by how the function is executed. This means that two invocations of the exact same function object could have differentthis
values if the invocation mechanisms are different (e.g.aFunction()
vs.aFunction.call(newThis)
vs.emitter.addEventListener("someEvent", aFunction);
, etc.) In your case,aFunction()
in non-strict mode runs the function withthis
set to the global object.When JavaScript files are
require
d as Node modules, the Node engine runs the module code inside of a wrapper function. That module-wrapping function is invoked with athis
set tomodule.exports
. (Recall, above, a function may be run with an abitrarythis
value.)Thus, you get different
this
values because eachthis
resides inside a different function: the first is inside of the Node-created module-wrapper function and the second is inside ofaFunction
.Summary:
In Javascript the value of
this
is determined when a function is called. Not when a function is created. In nodeJS in the outermost scope of a module the value ofthis
is the currentmodule.exports
object. When a function is called as a property of an object the value of this changes to the object it was called. You can remember this simply by the left-of-the-dot rule:caveats:
es2015
arrow function which don't have their own binding ofthis
.call
,apply
, andbind
can bend the rules regarding thethis
value.Example (NodeJS):
Output:
It's because the default global object in a Node.js module is the
exports
object, and you are callingtest()
which doesn't specifythis
. In traditional JS,this
points to the global object, withuse strict
,this
will be null.this
can point to anything, it just depends on how you call it.test()
: Uses the global object (exports
) asthis
, unless in strict mode, wherethis
will be null;test.call({})
ortest.apply({})
: You are specifying what to use asthis
(the first parameter)var obj = {testRef: test}; obj.testRef()
:this
is set to the left of the.
, that is,obj
Countering thefourtheye's answer
It is true that
this
in the top level of the module isexports
, but that doesn't necessarily mean thatthis
insidetest()
will also point to same thing as where it was called from.Attempting to prove that
this
and the global object both point toexports
To understand this, you need to understand that Node.js actually wraps your module code in to a function, like this
Detailed explanation can be found in this answer.
Now, this wrapped function is actually invoked like this
So,
this
, at the module level, is actually theexports
object.You can confirm that like this