node.js模块和函数中"this"的含义

Gök*_*dal 35 javascript node.js

我有一个加载的JavaScript文件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"
);
Run Code Online (Sandbox Code Playgroud)

我的问题是:this在var中a = this;是一个空对象,而this函数中的语句是node.js全局对象的阴影.我知道this关键字在函数中有所不同,但我无法理解为什么第一个this不等于全局,this而函数等于全局.

如何node.js的注入global,以this在功能范围,以及它为什么不其注入到模块的范围?

aps*_*ers 57

以下是澄清情况必须了解的一些基本事实:

  • 在Node模块的顶级代码中,this相当于module.exports.这是你看到的空对象.

  • 当您使用this在函数中,值this之前重新确定每一个执行的功能,并且它的值由下式确定如何执行该功能.这意味着this如果调用机制不同(例如aFunction()vs. aFunction.call(newThis)vs. emitter.addEventListener("someEvent", aFunction);等),则完全相同的函数对象的两次调用可以具有不同的值.在您的情况下,aFunction()在非严格模式下运行具有this设置为全局对象的函数.

  • 当JavaScript文件require作为节点模块时,Node引擎在包装函数内运行模块代码.使用thisset to 调用该模块包装函数module.exports.(回想一下,上面的函数可能会以一个abitrary this值运行.)

因此,您获得不同的this值,因为每个值都this位于不同的函数内:第一个在Node创建的模块包装函数内部,第二个在内部aFunction.


the*_*eye 31

要理解这一点,您需要了解Node.js实际上将您的模块代码包装到一个函数中,就像这样

(function (exports, require, module, __filename, __dirname) {
    var test = function(){
        console.log('From test: '  + this);
    };
    console.log(this);
    test();
});
Run Code Online (Sandbox Code Playgroud)

详细解释可以在这个答案中找到.


现在,这个包装函数实际上是这样调用的

var args = [self.exports, require, self, filename, dirname];
return compiledWrapper.apply(self.exports, args);
Run Code Online (Sandbox Code Playgroud)

因此,this在模块级别,实际上是exports对象.

你可以这样确认

console.log(this, this === module.exports);
// {} true
Run Code Online (Sandbox Code Playgroud)


Wil*_*een 6

摘要:

在Javascript中,值this在调用函数时确定的。创建函数时不行。在模块最外部作用域的nodeJS中,其值this是当前module.exports对象。当函数被调用为对象的属性时,此值更改为被调用的对象。您可以简单地通过点对点规则记住这一点:

调用函数时,可以this通过查看函数调用的位置来确定的值。点左边的对象是的值this。如果点中没有剩余的对象,则其值this是该module.exports对象(window在浏览器中)。

注意事项:

  • 此规则不适用于es2015没有自身绑定的箭头功能this
  • 功能callapplybind可以弯曲有关this值的规则。

示例(NodeJS):

console.log(this);  // {} , this === module.exports which is an empty object for now

module.exports.foo = 5;

console.log(this);  // { foo:5 }

let obj = {
    func1: function () { console.log(this); },
    func2: () => { console.log(this); }
}

obj.func1();  // obj is left of the dot, so this is obj
obj.func2();  // arrow function don't have their own this
              // binding, so this is module.exports, which is{ foo:5 } 
Run Code Online (Sandbox Code Playgroud)

输出:

在此处输入图片说明