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

我有一个由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" ); 

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

node.js是如何在函数作用域中为其注入global ,为什么它不将它注入到模块作用域?

这里有几个基本的事实,你必须理解澄清的情况:

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

  • 当你在函数内部使用this函数的时候,这个函数的值是在函数的每次执行之前重新确定的,它的值是由函数的执行方式决定的 。 这意味着如果调用机制不同(例如aFunction()aFunction.call(newThis)emitter.addEventListener("someEvent", aFunction);等等,那么完全相同的函数对象的两个调用可能具有不同的this值。)在你的情况下,非严格模式下的aFunction()运行this设置为全局对象的函数。

  • 当JavaScript文件被require作为节点模块时,节点引擎在包装函数中运行模块代码。 这个模块包装函数调用this设置为module.exports 。 (回想一下,上面的函数可能会以this值的abitrary运行。)

因此,你得到不同的this值,因为它们都驻留在一个不同的函数中:第一个在Node创build的模块包装函数内部,第二个在函数内部。

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

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

详细的解释可以在这个答案中find。


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

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

所以,在模块级别,这实际上是exports对象。

你可以这样确认

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

这是因为Node.js模块中的默认全局对象是exports对象,而您正在调用test() ,它没有指定this 。 在传统的JS中, this指向全局对象, use strictthis将是空的。

this可以指向任何东西,这取决于你如何调用它。

  • test() :使用全局对象( exports ),除非在严格模式下, this将是null;
  • test.call({})test.apply({}) :您正在指定要使用的内容(第一个参数)
  • var obj = {testRef: test}; obj.testRef() var obj = {testRef: test}; obj.testRef()this是设置在左边的. ,就是obj

反驳这个问题的答案

确实, this在模块的顶层是exports ,但这并不一定意味着this内部test()也会指向它被调用的地方。


试图certificatethis和全球对象都指向exports

  myGLobal = 5; this.myGlobal; // 5