Node.js变量声明和作用域

51
当我在node.js中输入这个时,我得到了 undefined
var testContext = 15;
function testFunction() {
  console.log(this.testContext);
}
testFunction();
=>undefined

没有使用 var 关键字,它通过了(=>15)。在 Chrome 控制台中可以工作并且可以使用或不使用 var 关键字。


你尝试过在调用console.log()时删除this.吗? - Justin Niessner
4
“this”关键字在这里是做什么用的? - Bergi
@JustinNiessner 移除 this. 后可以正常工作。为什么?如果在另一个 node.js 文件中调用了 testFunction();,它是否仍然有效?(已测试是的,但为什么?) - Weishi Z
发现它是 JavaScript 的“词法作用域”。 - Weishi Z
4个回答

63

使用var时在Node中无法工作,因为testContext是当前模块的本地变量。您应该直接引用它:console.log(testContext);

当您不键入var时,会发生的是testContext现在是整个Node进程中的全局变量

在Chrome(或任何其他浏览器 - 好吧,我不确定旧版IE...)中,在示例中是否使用var都没有关系,testContext将进入全局上下文,即window

顺便说一下,“全局上下文”是JS中函数调用的默认this


我知道这可能没有实际用途,可能,但是有没有办法在节点中访问globals的实际全局变量?只是好奇。 - undefined

22
关键区别在于Node.js中的所有模块(脚本文件)都在它们自己的闭包中执行,而Chrome和其他浏览器直接在全局作用域中执行所有脚本文件。
这在全局文档中有提到:

一些对象实际上不在全局作用域中,而是在模块作用域中 - 这将被注明。

你在Node模块中声明的var将被隔离到其中一个闭包中,这就是为什么你必须导出成员以供其他模块使用。
但是,当调用一个没有特定上下文的function时,通常会默认为全局对象 - 在Node中方便地称为global
function testFunction() {
    return this;
}

console.log(testFunction() === global); // true

如果没有使用var来声明,testContext将默认为全局变量defined as a global

testContext = 15;
console.log(global.testContext); // 15

我认为你所说的“闭包”和“作用域”,应该是指“执行上下文”。 - RobG
@RobG 它们仍然是有效且常用的术语。但是,是的,ECMA将它们定义为执行上下文 - Jonathan Lonowski
它们经常被错误地使用,其他一些参考资料包括:闭包作用域执行上下文 - RobG
@RobG 我知道它们各自的含义。但是,这种区分有点学究。这没关系,我同意你的看法。但是,“scope”仍然是描述一般概念的有效术语,而[[Scope]]、作用域链和执行上下文则是更具体的实现细节。 - Jonathan Lonowski

5

文档中所述:

在Node.js模块中声明的变量将局限于该模块。

因此,与模块上下文中的 var testContext 不同,这里的上下文是 global

您也可以使用以下方法:

global.testContext = 15;
function testFunction() {
  console.log(this.testContext);
}
testFunction();

0

我认为问题与 this 关键字有关。如果你执行 console.log(this),你会看到 testContext 没有被定义。你可以尝试:

this.testContext = 15;
function testFunction() {
  console.log(this.testContext);
}
testFunction();

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接