Node.js: What is the context of the `this` operato

2019-01-28 21:27发布

问题:

This question already has an answer here:

  • What does “this” mean in a nodejs module? 1 answer

The code

I write the following code and save it as test.js:

var foo = 'I am local';
global.foo = 'I am global';

function print () {
     console.log(this.foo);
};

print(); 
console.log (this.foo); 

I then run it in the terminal with the command node test.js and it returns:

I am global
undefined

The question

Why does it not return:

I am global
I am global

?

回答1:

Inside a Node module, this by design refers to module's exports object:

console.log(this === exports); // true

Making console.log(this.foo) equivalent to console.log(exports.foo).

In other words, neither does this refer to the global object nor do local variables magically become properties of exports.

Since exports.foo doesn't exist, you get undefined.



回答2:

All script files in Node.js are executed in their own execution context, while browsers execute all script files within the global execution context. When calling a function without a specific context, it will normally be defaulted to the global object in Node.

print(); //global execution context -> 'I am global'
console.log (this.foo); // no context -> undefined


回答3:

The this property of a function is set when the function is called and by default points to the object calling the function unless the value is set by methods such as bind, apply or call.

It is worth to note that a module (equivalent to a file) in Node is wrapped in a function() like this:

NativeModule.wrapper = [
  ‘(function (exports, require, module, __filename, __dirname) { ‘,
  ‘\n});’
];

This means that all the code snippets below are actually executed inside this wrapper function. See Where are vars stored in Nodejs for more detailed information.

Console.log(this) inside a function

The following code:

var apple = ‘red’;          // private variable in the wrapper function 
global.apple = ‘yellow’;    // property on the global object 

var foo = function () {

    var apple = ‘green’;
    console.log (this.apple);
}

foo();

returns yellow because an inner function cannot access the this value of any outer functions and in case of such inner functions it is standard behaviour of this to default to the global object (the window object in browsers).

Console.log(this) inside an object

The following code:

var apple = ‘red’;          // private variable in the wrapper function
global.apple = ‘yellow’;    // property on the global object 

var myObject = {

    orange: ‘orange’,
    print: function () {

    console.log (this.orange);
    console.log (this.melon);   
}}

myObject.print();

returns orange and undefined because it is myObject calling print. It returns undefined in relation to this.melon, because myObject has no property with the name melon.

Console.log(this) in module scope

The console.log command is a property on Node´s global object with the value of a function and therefore you would expect the following code

global.apple = ‘yellow’;
global.console.apple = 'yellow';

console.log(this.apple);

to return yellow as console.log() is the same as global.console.log(). This means that console.log() is called by the global object and therefore you would expect this to point to either global.apple or global.console.apple. However some of the functions on the global object is actually executed in module scope (see Global objects) and in this scope the designers of Node have chosen to set the value of this to the object exports, which is passed as a parameter to the function wrapping a Node module.

The above code therefore returns undefined because exports does not have a property with the name apple.