为什么var可以重复声明

因为编辑器会在判断有已经声明的同名变量时忽略var,然后直接赋值

原理

在JS代码运行过程中:

  • 引擎负责整个代码的编译以及运行
  • 编译器则负责词法分析、语法分析、代码生成等工作
  • 作用域负责维护所有的标识符(变量)。
var a = 2;
var a = 3;
a = 4;
alert(a); // 4

当我们执行上面的代码时,我们可以简单的理解为新变量分配一块儿内存,命名为a,并赋值为2,但在运行的时候编译器与引擎还会进行两项额外的操作:判断变量是否已经声明

  1. 重复声明时:首先编译器对代码进行分析拆解,从左至右遇见var a,则编译器会询问作用域是否已经存在叫a的变量了。如果不存在,则招呼作用域声明一个新的变量a;若已经存在,则忽略 var 继续向下编译,这时 a = 2被编译成可执行的代码供引擎使用。
  2. 赋值时:引擎遇见a=2时同样会询问在当前的作用域下是否有变量a。若存在,则将a赋值为2(由于第一步编译器忽略了重复声明的var,且作用域中已经有a,所以重复声明会发生值的覆盖而不会报错);若不存在,则顺着作用域链向上查找,若最终找到了变量a则将其赋值2,若没有找到,则招呼作用域声明一个变量a并赋值为2(这就是为什么第二段代码可以正确执行且a变量为全局变量的原因,当然,在严格模式下JS会直接抛出异常:a is not defined)。
在JavaScript中,使用 `var` 关键字声明变量时允许重复命名,这是其语法特性之一。具体来说: - 使用 `var` 重复声明一个已经通过 `var` 声明变量是合法的,并且不会引发语法错误。 - 如果重复声明的同时进行了赋值,则该操作相当于对已存在的变量进行重新赋值。 - 如果仅重复声明而不赋值,则该语句不会对现有变量产生任何影响[^2]。 例如,以下代码展示了 `var` 变量重复声明行为: ```javascript var a = 100; var a = 200; // 重复声明并赋值 console.log(a); // 输出 200 ``` 在函数作用域中,`var` 的重复声明规则同样适用,但需要注意变量提升(hoisting)的影响。变量提升是指 JavaScript 引擎会将变量和函数声明提升到其作用域的顶部。这意味着即使变量是在函数内部稍后的位置声明的,它也会被视为存在于函数作用域的顶部。例如: ```javascript function fn() { console.log(a); // undefined var a = 200; console.log(a); // 200 } fn(); ``` 上述代码中,变量 `a` 的声明被提升到了函数作用域的顶部,但其赋值操作仍然保留在原位置。因此,在首次调用 `console.log(a)` 时,变量 `a` 已经存在,但尚未被赋值,此时它的值为 `undefined` [^3]。 此外,在全局作用域中使用 `var` 声明变量会成为 `window` 对象的属性,这也意味着可以通过 `window` 对象访问这些变量。例如: ```javascript var globalVar = "global"; console.log(window.globalVar); // 输出 "global" ``` 相比之下,使用 `let` 和 `const` 声明变量时不允许重复声明,这有助于避免潜在的命名冲突和错误,这也是推荐使用 `let` 和 `const` 而非 `var` 的原因之一。 综上所述,虽然 `var` 允许重复声明变量,但在实际开发中应谨慎使用这一特性,以避免代码中出现难以调试的问题。随着 ES6 的普及,使用 `let` 和 `const` 成为了更佳实践,因为它们提供了更严格的变量管理机制,有助于编写更清晰和可靠的代码 [^4]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值