本文详细解析JavaScript中var、let、const三种变量声明方式的核心差异。重点对比重复声明限制、变量提升机制、暂时性死区(TDZ)特性,以及块级作用域对循环变量的影响。通过具体代码示例说明全局变量挂载window对象的规则,帮助开发者根据场景选择正确的声明方式,避免常见运行时错误。
在JavaScript开发中,理解var、let和const三种变量声明方式的区别至关重要。
首先,三者对重复声明的支持不同。var允许在同一作用域内重复声明同一变量,而let和const均禁止重复声明,若尝试重复声明会抛出语法错误。
1.1 var
var a = 1;
var a = 2;
console.log(a);
输出结果:
2
1.2 let
let b = 3;
let b = 4;
console.log(b);
输出结果:
Uncaught SyntaxError: Identifier 'b' has already been declared
1.3 const
const c = 5;
const c = 6;
console.log(c);
输出结果:
Uncaught SyntaxError: Identifier 'c' has already been declared
其次,变量提升行为存在显著差异。var声明的变量会发生提升,但仅提升声明部分而不提升赋值;let和const则完全不支持变量提升。
在var的情况下,即使代码书写顺序在赋值之后,声明仍会被提升到作用域顶部。而使用let或const时,若在声明前访问变量,将导致引用错误。
2.1 var
a=2;
console.log(a);
var a = 1;
输出结果:
2
2.2 let
a=2;
console.log(a);
let a = 1;
输出结果:
Uncaught ReferenceError: Cannot access 'a' before initialization at index.html:28
2.3 const
a=2;
console.log(a);
const a = 1;
输出结果:
Uncaught ReferenceError: Cannot access 'a' before initialization at index.html:28
第三,暂时性死区(TDZ)是let和const特有的机制。只要作用域内存在let或const声明,所涉及的变量即被绑定至该区域,不再受外部作用域影响。
var不存在暂时性死区,访问未初始化的var变量会返回undefined。而let和const在声明前访问会直接报错,确保变量状态明确。
3.1 var
var a = 1;
function fun() {
console.log(a);
var a = 2;
}
fun();
输出结果:
undefined
3.2 let
let a = 1;
function fun() {
console.log(a);
let a = 2;
}
fun();
输出结果:
Uncaught ReferenceError: Cannot access 'a' before initialization
3.3 conset
let a = 1;
function fun() {
console.log(a);
const a = 2;
}
fun();
输出结果:
Uncaught ReferenceError: Cannot access 'a' before initialization
第四,全局作用域下的表现不同。在全局环境中,var声明的变量及function声明的函数会自动成为window对象的属性或方法。
这意味着通过var声明的全局变量可通过window对象访问,而let和const声明的全局变量则不会挂载到window上。
var a = 1;
function add() { };
console.log(window.a === a);
console.log(window.add === add);
输出结果:
true true
最后,块级作用域的控制能力不同。var不具备块级作用域,而let和const具备。
在for循环中,使用var定义的变量i在循环结束后仍可在外部访问,值为3。若改用定义,则循环结束后i未定义,抛出ReferenceError。
for (var i = 0; i < 3; i++) {
// console.log(i);
}
console.log(i);
输出结果:
3
使用let在for循环中定义变量i:
for (let i = 0; i < 3; i++) {
// console.log(i);
}
console.log(i);
输出结果:
Uncaught ReferenceError: i is not defined
总结而言,var、let、const在重复声明、变量提升、暂时性死区及块级作用域方面各有特点,开发者应根据具体场景选择合适的声明方式。