繁体   English   中英

变量不会在全局上下文中注册,为什么?

[英]The variables won't registered in the global context, why?

我曾经认为,不在函数内部的所有参数和命名函数都应在全局上下文(在“ this”上下文中)中注册,但是以下代码使我感到困惑。

为什么没有关键字var的变量可以在“此”上下文中注册,而其他变量则不能?

g_var_1 = "I'm in the global context";
var g_var_2 = "I'm not in the global context";

function g_func() {
    console.log("why I'm not in the global context?");
}

(function() {
    console.log(this);          //do not see g_var_2 and g_func
})();

//test the global context variables
(function() {
    console.log(this.g_var_1);  //ok
    console.log(this.g_var_2);  //undefined
    console.log(g_var_1);       //ok
    console.log(g_var_2);       //ok
    this.g_func();              //Error
    g_func();                   //ok
})();

首先,由于它被标记为node.js,因此您应该意识到,node.js中的所有代码都包含在其中的node.js模块实际上位于函数本身内部。

每个node.js模块都包裹在这样的内部:

(function (exports, require, module, __filename, __dirname) {
    // Your module code actually lives in here
});

因此,您在node.js模块的顶级范围内声明的内容实际上不在顶级范围内-它位于包装函数中。

其次,只能通过讨论严格模式和非严格模式来解决这个问题。 由于似乎可以运行代码,因此必须以非严格模式运行它。 为此,您将获得以下规则:

  1. 您分配给任何未声明的变量都将成为隐式全局变量。
  2. 您调用的任何普通函数都会this指针设置为全局对象。

因此,现在使用这两个规则,让我们看看您的结果:

g_var1成为全局g_var1

g_var2不是全局的。 它是在模块范围中明确声明的,如上所述,它不是顶层的。 它在模块函数包装器内。

g_func同样不是全局的。 这是模块级别的功能。

然后,当您执行此操作时:

(function() {
    console.log(this);          //do not see g_var_2 and g_func
})();

this被设置为global对象,你没有看到g_var_2g_func因为正如我刚才所说,他们不是全局的,但有模块范围。

然后,当您运行此命令时:

//test the global context variables
(function() {
    console.log(this.g_var_1);  //ok
    console.log(this.g_var_2);  //undefined
    console.log(g_var_1);       //ok
    console.log(g_var_2);       //ok
    this.g_func();              //Error
    g_func();                   //ok
})();

this设置为全局对象。 g_var_1是真正的全局this.g_var_1因此this.g_var_1有效。 由于g_var_2g_func不是全局符号,因此无法通过this引用它们。

但是,所有g_var_1g_var_2g_func都在父范围内,因此您可以自己引用它们。


现在,让我们谈谈如何在strict模式下编程。 strict模式是JavaScript努力摆脱可怕的事情它诞生与自动完成未声明的变量为全局和自动的值设置语言this在普通函数全局对象。 这两件事导致了很多偶然的错误,这些错误中的代码没有报告错误,但是由于一些轻微的键入错误而没有达到您的预期目的。

因此,在strict模式下,如果尝试使用未声明的变量,则会立即收到错误(逻辑上是应解决的问题)。 并且,在常规函数中, this值的值是undefined

因此,在您的方案中:

分配给g_var_1将立即导致错误。 为了完全使用它,必须将其声明为全局变量或模块变量。 声明了其他变量,因此它们的范围保持不变。

在此里面:

(function() {
    console.log(this);
})();

thisundefined 然后,在这里:

//test the global context variables
(function() {
    console.log(this.g_var_1);  //ok
    console.log(this.g_var_2);  //undefined
    console.log(g_var_1);       //ok
    console.log(g_var_2);       //ok
    this.g_func();              //Error
    g_func();                   //ok
})();

this将是未定义的,因此它的所有引用均无效。 通常声明的变量按预期工作。

因为当您在var名称之前使用'var'时,您就声明它是全局的。 然后,例如,如果要在函数内部重新声明该变量,则在函数内部的名称之前添加“ var”。

我将这张图片放在一起是为了更好地解释全局范围如何在Node.js中工作。

  • 当您运行* .js文件(在这种情况下为“ main.js”)时,您不在全局范围内,而是在“ main”模块中,但如果声明的标识符不带关键字[var let const]它会自动变为全局变量!

myVar // same as global.myVar (in Node) // same as window.myVar (in the browser)

  • 当您声明[g_var_1]成为全局变量时,基本上就声明了[global.g_var_1]

  • [this]关键字是指当前模块(作用域),而不是全局范围

  • 在main.js中,我们运行[require('./ module1.js')]和[require('./ module2.js')]方法,这基本上告诉Node Module1.js和module2.js模块共享相同的全球范围

  • 如果我们在运行main.js文件时在module1.js [mod1Var]或[global.mod1Var]中声明,则可以访问该数据!

  • 注意 :

Node并非旨在在全局范围内声明变量,而只是为了更好地说明其工作原理(在其“ Node.js”中,我们使用多个节点(模块)来避免名称冲突并使用出色的结构)

您应避免使用不带关键字[var let const]的标识符,在严格模式下,这是不允许的!

Node.js基本结构

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM