I have this piece of code :
var obj1;
var obj2;
function x() {
obj1 = this;
}
function y() {
obj2 = this;
}
x();
y();
console.log(obj1 === o
Created a table to show the this
value under different scopes and modes:
Note: In Node environment, the value of this
outside the function means that this
value is outside of
a function declaration but within the anonymous function wrapper created by node.js for achieving the module scope.
Node explicitly sets this
to the module exports here:
const result = compiledWrapper.apply(this.exports, args);
What apply
does is explicitly fixate the this
value (and parameters) - in this case - it sets it to this.exports
. For example you can do:
(function() { console.log(this.x); }).apply({x:3}); // alerts 3
Node override's the default behavior. It has to, however, call functions inside the object with global
- as is mandated by the JS spec.
In the Browser-Context the last this points to the Windowobject, which does exist in Node-Context. Therefore the last this is an empty object. The occurrences of this in the functions however point to some global object in the Node-Context.
The difference is pretty simple
In the node environment :
this refers to module.exports
or exports
for short.
but inside a function this is refering to the entire Node.js package.
you can see it if you log to the console the following :
function test(){
console.log('this inside a function = ',this);
}
console.log('this outside a function = ',this);
test();
Whereas in the browser environment this inside a function or outside a function is referring to the window object unless you are using the new keyword which is another story.
Execute the previous example in both Node.js and browser environments and you will understand.
I have no Node.js server in a hand right now, but I think you can yourself research this question, and give answer for us :D see code below
Try to run:
console.log(this.constructor.name+" "+obj1.constructor.name+" "+obj2.constructor.name);
And also you can debug "Parent Class" name in a function:
function x() {
console.log("x this: "+this.constructor.name);
obj1 = this;
}
function y() {
console.log("y this: "+this.constructor.name);
obj2 = this;
}
And for view Object methods / properties you can use something like this:
for (a in obj2) {
console.log("obj2." + a + " = " + obj2[a]);
}
In the browser, running in the global scope, this
is always window
in your example
var obj1;
var obj2;
function x() {
obj1 = this; // window
}
function y() {
obj2 = this; // window
}
x();
y();
console.log(obj1 === obj2); // window === window = true
console.log(obj1 === this); // window === window = true
This is not how it works in Node. In Node.js all modules (script files) are executed in their own closure while browsers execute all script files directly within the global scope.
In other words, in just about any file running in Node, this
will just be an empty object, as Node wraps the code in an anonymous function that is called immediately, and you'd access the global scope within that context with GLOBAL
instead.
This is also mentioned in the Globals documentation:
Some of these objects aren't actually in the global scope but in the module scope - this will be noted.
However, when calling a function without a specific context in Node.js, it will normally be defaulted to the global object - The same GLOBAL mentioned earlier, as it's execution context.
So outside the functions, this
is an empty object, as the code is wrapped in a function by Node, to create it's own execution context for every module (script file), while inside the functions, because they are called with no specified execution context, this
is the Node GLOBAL
object
In Node.js you'd get
var obj1;
var obj2;
function x() {
obj1 = this; // GLOBAL
}
function y() {
obj2 = this; // GLOBAL
}
x();
y();
console.log(obj1 === obj2); // GLOBAL === GLOBAL = true
console.log(obj1 === this); // GLOBAL === {} = false
Where the last this
is indeed an empty object, as explained above
For completeness, it's worth noting that in strict mode, you'd get the same result in a browser (true, false
) as in Node, but that's because the variables are just the opposite of what they are in Node
"use strict"
var obj1;
var obj2;
function x() {
obj1 = this; // undefined
}
function y() {
obj2 = this; // undefined
}
x();
y();
console.log(obj1 === obj2); // undefined === undefined = true
console.log(obj1 === this); // undefined === window = false
This is because the value passed as this
to a function in strict mode is not forced into being an object (a.k.a. "boxed").
For a normal function in non-strict mode, this
is always an object, and it's always the global object if called with an undefined
or null
this-value, i.e. without a specific execution context.
Not only is automatic boxing a performance cost, but exposing the global object in browsers is a security hazard, because the global object provides access to functionality that "secure" JavaScript environments must restrict.
Thus for a strict mode function, the specified this
is not boxed into an object, and if unspecified, this
will be undefined
inside functions, as shown above, but this
will still be the window in the global scope.
The same thing happens in strict-mode in Node.js, where this
inside the functions is no longer GLOBAL
but undefined
, and this
outside the functions will still be the same empty object, and the end result will still be true, false
, but the value of this
will be different in strict-mode in Node.js as well.