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 strict
, this
将是空的。
this
可以指向任何东西,这取决于你如何调用它。
-
test()
:使用全局对象(exports
),除非在严格模式下,this
将是null; -
test.call({})
或test.apply({})
:您正在指定要使用的内容(第一个参数) -
var obj = {testRef: test}; obj.testRef()
var obj = {testRef: test}; obj.testRef()
:this
是设置在左边的.
,就是obj
反驳这个问题的答案
确实,在模块的顶层是exports
,但这并不一定意味着this
内部的test()
也会指向与它被调用的地方相同的东西。
试图certificatethis
和全球对象都指向exports
myGLobal = 5; this.myGlobal; // 5