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

时间:2014-03-31 19:20:31

标签: javascript node.js

我有一个由require加载的JavaScript文件。

// 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"
);

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

node.js如何在函数作用域中向global注入this,以及它为什么不将它注入模块作用域?

4 个答案:

答案 0 :(得分:49)

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

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

  • 在函数内部使用this时,{em>的每次执行之前都会重新确定this的值,其值为determined by how the function is executed。这意味着如果调用机制不同(例如thisaFunction()aFunction.call(newThis)等,则完全相同的函数对象的两次调用可能具有不同的emitter.addEventListener("someEvent", aFunction);值。 )在您的情况下,非严格模式下的aFunction()运行将this设置为全局对象的函数。

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

因此,您获得了不同的this值,因为每个this都驻留在不同的函数中:第一个位于Node创建的模块包装函数内部,第二个位于{{1}内部}。

答案 1 :(得分:29)

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

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

详细说明可在this answer

中找到

现在,这个包装函数是actually invoked like this

var args = [self.exports, require, self, filename, dirname];
return compiledWrapper.apply(self.exports, args);

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

您可以像这样确认

console.log(this, this === module.exports);
// {} true

答案 2 :(得分:1)

摘要:

在Javascript中,{strong>调用函数时确定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 } 

输出:

enter image description here

答案 3 :(得分:-1)

这是因为Node.js模块中的默认全局对象是exports对象,而您正在调用未指定test()的{​​{1}}。在传统的JS中,this指向全局对象,thisuse strict将为空。

this可以指向任何东西,它只取决于你如何称呼它。

  • this:将全局对象(test())用作exports,除非在严格模式下,this为空;
  • thistest.call({}):您正在指定要用作test.apply({})的内容(第一个参数)
  • thisvar obj = {testRef: test}; obj.testRef()设置在this的左侧,即.

打击thefourtheye's answer

模块顶层的obj确实是this,但这并不一定意味着exports内的this也会指向同一个它被称为的地方。

试图证明test()和全局对象都指向this

exports