node.js:在全局范围中混淆使用'this'

Jef*_*Cyr 10 javascript node.js

我最近一直在玩node.js而且我遇到了关于this模块全局范围内使用的奇怪行为.

this 绑定到全局范围中的module.exports:

console.log(this === exports); // -> true
Run Code Online (Sandbox Code Playgroud)

但是this在方法范围内绑定到全局:

(function() { console.log(this === global); })(); // -> true
Run Code Online (Sandbox Code Playgroud)

这也导致了这种令人困惑的行为:

this.Foo = "Weird";
console.log(Foo); // -> throws undefined

(function() { this.Bar = "Weird"; })();
console.log(Bar); // -> "Weird"
Run Code Online (Sandbox Code Playgroud)

我想解决方案是永远不要this在全局范围内使用并明确使用extendsglobal替代,但是这背后是否存在逻辑,或者它是node.js中的错误或限制?

jAn*_*ndy 7

其背后的"逻辑"是,值this始终取决于函数的调用方式.

在您的情况下,您有一个自执行的匿名函数,在那里,this始终引用全局对象(非严格模式)或undefined(ES5严格).

如果要访问"外部" this值,可以在执行该函数之前存储引用,例如

var outerScope = this;

(function() { outerScope.Bar = "Weird"; })();
console.log(Foo); // -> throws undefined
Run Code Online (Sandbox Code Playgroud)

或者重新.bind()定义自己的功能范围

(function() { this.Bar = "Weird"; }).bind(this)();
Run Code Online (Sandbox Code Playgroud)


Dag*_*bit 1

this在开发一个简单的 CommonJS 模块实现时,我必须考虑在模块的全局范围内做什么;规范中没有解决这个问题。

我一开始也将它设置为exports对象,因为我认为这会很有用,但后来发现我需要“模块化”一些代码this,这些代码用于获取全局对象的句柄,所以我改this回全局对象为模块代码提供尽可能接近“正常”的环境。

我们只能猜测为什么节点会这样设置(或者询问作者),但我的猜测是这样做只是因为这似乎是一个有用的想法,类似于您可以在节点中为module对象提供属性的方式exports并将其反映在模块的实际中exports(这种行为也不是规范的一部分,但也不违反规范)。

至于你的问题中关于函数this引用的部分global,正如其他答案所解释的那样,这就是有效的方法this;这不是特定于节点的行为,而是一种奇怪的 JavaScript 行为。