繁体   English   中英

在同一范围内两次声明 Javascript 变量 - 这是一个问题吗?

[英]Declaring a Javascript variable twice in same scope - Is it an issue?

以下代码会导致任何问题吗?:

var a = 1;
var a = 2;

我的理解是 javascript 变量是在作用域的开始处声明的。 例如:

var foo = 'a';
foo = 'b';
var bar = 'c';

处理为:

var foo;
var bar;
foo = 'a';
foo = 'b';
bar = 'c';

因此,我的初始代码片段会变成:

var a;
a = 1;
a = 2;

或者它会变成:

var a;
var a;
a = 1;
a = 2;

我知道在同一范围内两次声明一个 javascript 变量并不是一个好习惯,但我对这样做的影响更感兴趣。

正如您所说,通过两次以上相同的 var,JavaScript 将该声明移动到范围的顶部,然后您的代码将变成这样:

var a;
a = 1;
a = 2;

因此,它不会给我们任何错误。

同样的行为发生在for循环中(它们的标头中没有局部作用域),所以下面的代码非常常见:

for (var i = 0; i < n; i++) {
    // ...
}
for (var i = 0; i < m; i++) {
    // ...
}

这就是为什么像Douglas Crockford这样的 JavaScript 专家建议程序员手动将这些声明移到作用域的顶部:

var i;    // declare here
for (i = 0; i < n; i++) {    // initialize here...
    // ...
}
for (i = 0; i < m; i++) {    // ... and here
    // ...
}

两次声明同一个变量与声明一次一样好。 以下声明不会带来任何影响。

var a, a;

在下面的情况下,您只是覆盖了变量 foo。 如果您在本地和全局范围内定义了 foo,这将产生影响。 JS 会先在局部范围内搜索 foo ,如果没有找到就会在全局范围内查找。

var foo;
var bar;
foo = 'a';
foo = 'b';
bar = 'c';

让我们尝试转录ECMAScript® 2021 语言规范所说的内容。

首先,根据JavaScript:Understanding the Weird Parts有运行代码的两个阶段:创建阶段执行阶段 从概念上讲,这就像代码被处理两次(不执行,处理)。

对于var a = 5; 声明这正在发生:

  • 创建阶段:标识符a 的内存分配和设置到该内存的未定义值(所谓的提升
  • 执行阶段:将值5放入与标识符a关联的内存中(而不是undefined

现在ECMAScript® 2021 语言规范的14.3.2 变量语句部分说明了这一点

var语句声明了作用域为正在运行的执行上下文的VariableEnvironment变量 Var 变量在包含环境记录的实例化时创建,并在创建时初始化为未定义 在任何VariableEnvironment的范围内,一个公共BindingIdentifier可能出现在多个VariableDeclaration 中,但这些声明共同定义了一个变量。 由带有InitializerVariableDeclaration定义的变量在执行 VariableDeclaration 时被分配其 Initializer 的AssignmentExpression值,而不是在创建变量时。

让我们一行一行地检查它。

在任何VariableEnvironment的范围内,一个公共的BindingIdentifier可能出现在多个VariableDeclaration 中

在这种情况下BindingIdentifier只是一个标识符。 声明意味着这些语法是正式允许的。

var a;
var a;
var a = 1;
var a = 2;
var a, a;
var a = 1, a = 2;

但是这些声明共同定义了一个变量

直接说是同一个变量,只分配了一块内存。

从概念上讲,您可能会认为,如果在创建阶段带有identifier变量( a是我们的例子)已经创建,它的创建将被跳过(前面的语句已经分配了内存并将未定义的设置放入其中)。

VariableDeclaration初始化程序中定义的变量被分配在执行VariableDeclaration其初始化器的AssignmentExpression的值,而不是当在创建可变

只是进一步强调此语句的赋值(发生在执行阶段)和变量创建(发生在创建阶段)之间的区别

var a = 5;

解释

现在让我们总结一下我们所知道的。 规范正式支持此语法。 这意味着创建一个变量(一个内存位置来保存值)

var a = 1;
var a = 2;

吊装无关 吊装仍在照常进行。

console.log(a) // this is undefined
var a = 1;
var a = 2;

分配将在执行阶段逐行进行,更改相同内存位置的值。

console.log(a) // undefined
var a = 1;
console.log(a) // 1
var a = 2;
console.log(a) // 2

由于 javascript 的变量提升功能,这样的重复变量声明不会导致任何问题。 所以在你的 DOM 中,无论你在哪里声明了变量但分配(或)未分配,它们将在编译期间放置在顶部。

Example:
    var foo='hai!';
    bar='welcome!';
    var bar;

您可能期望上面的代码片段应该抛出“未识别”错误,但 javascript 仍然通过将 bar 变量的声明放在顶部来管理它。 因此,即使在变量声明之前,它的值也可以分配,而不是其他语言。

希望这能在一定程度上帮助你

如果您两次初始化同一个变量,控制台上将不会出现错误,但如果您正在处理某个应用程序(例如猜我的数字)并希望将所有元素重置为初始状态。 所有元素都将被设置为初始状态,但被初始化两次的变量将仅坚持其修改后的值。 例如,如果初始分数是 20,然后修改为某个数字 15,现在按下重置按钮以将值设置为初始值,但不会。

暂无
暂无

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

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