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