在JavaScript的变量声明体系中,var
、let
和const
是三个核心关键字,它们在作用域、变量提升机制、赋值规则等方面存在显著差异。正确理解这些差异是写出规范JavaScript代码的基础。
🔍 作用域的不同表现
var:函数作用域 🔑
var
声明的变量遵循函数作用域规则,在函数内部声明的变量仅在函数范围内可见,在全局作用域声明的变量会成为全局对象的属性。
function example() {
if (true) {
var x = 10; // 函数作用域内的变量
}
console.log(x); // 输出 10,在函数内可访问
}
example();
let和const:块级作用域 🧱
let
和const
声明的变量属于块级作用域,仅在包含它们的{}
代码块内有效,常见于if
、for
、while
等结构中。
function example() {
if (true) {
let y = 20; // 块级作用域
const z = 30; // 块级作用域
}
console.log(y); // 报错:y is not defined
console.log(z); // 报错:z is not defined
}
example();
⏪ 变量提升的差异
var的变量提升 🚀
var
声明的变量会被提升到函数或全局作用域的顶部,但初始值为undefined
,这可能导致意想不到的结果。
console.log(a); // 输出 undefined(变量已提升但未赋值)
var a = 5;
console.log(a); // 输出 5
let和const的暂时性死区 ⚠️
let
和const
声明的变量也会被提升,但存在"暂时性死区"(TDZ),在声明前访问会抛出错误。
console.log(b); // 报错:Cannot access 'b' before initialization
let b = 10;
console.log(c); // 报错:Cannot access 'c' before initialization
const c = 20;
✏️ 赋值规则的区别
var和let:可重新赋值 ✔️
这两个关键字声明的变量允许重新赋值,适用于值可能变化的场景。
// var的重新赋值
var x = 1;
x = 2; // 合法,x现在为2
// let的重新赋值
let y = 10;
y = 20; // 合法,y现在为20
const:禁止重新赋值 ❌
const
声明的变量必须在声明时赋值,且后续禁止重新赋值,但对于引用类型可以修改其属性。
const z = 1;
z = 2; // 报错:Assignment to constant variable
const obj = { name: 'Alice' };
obj.name = 'Bob'; // 合法,修改对象属性
obj = {}; // 报错:禁止重新赋值
📝 变量重声明的限制
var:允许重复声明 🔄
在同一作用域内可以多次声明同一个var
变量,后声明会覆盖前声明。
var a = 1;
var a = 2; // 合法,a现在为2
function demo() {
var b = 10;
var b = 20; // 合法,函数作用域内重复声明
}
let和const:禁止重复声明 🚫
在同一作用域内使用let
或const
重复声明同一个变量会抛出错误。
let c = 1;
let c = 2; // 报错:Identifier 'c' has already been declared
const d = 10;
const d = 20; // 报错:Identifier 'd' has already been declared
if (true) {
let e = 5;
}
let e = 10; // 报错:块级作用域外重复声明
📌 使用场景建议
const:优先选择的声明方式 🌟
- 适用于值不会改变的变量,如配置项、枚举值等
- 对于对象和数组等引用类型,虽然不能重新赋值,但可以安全地修改其内容
- 强制代码的不可变性,减少意外赋值导致的bug
let:需要动态赋值的场景 📌
- 用于值可能变化的变量,如循环计数器、临时存储值的变量
- 在块级作用域中限制变量的可见范围,避免命名冲突
- 替代
var
作为默认的变量声明方式
var:谨慎使用的遗留选项 ⚠️
- 仅在需要兼容老旧JavaScript环境时使用
- 在某些特殊场景下(如函数作用域的变量)可能仍有应用
- 尽量避免在新代码中使用
var
声明变量
📊 总结对比表
特性 | var | let | const |
---|---|---|---|
作用域 | 函数作用域 | 块级作用域 | 块级作用域 |
变量提升 | 提升为undefined | 存在TDZ,声明前不可用 | 存在TDZ,声明前不可用 |
重新赋值 | 允许 | 允许 | 禁止 |
重新声明 | 允许 | 禁止 | 禁止 |
初始值要求 | 无 | 无 | 必须初始化 |
推荐使用场景 | 老旧代码兼容 | 可变变量 | 不可变变量 |
🌟 最佳实践
- 始终优先使用
const
声明变量,仅在确实需要改变值时使用let
- 完全避免使用
var
,除非有特殊的兼容性需求 - 利用块级作用域特性,将变量的作用域限制在最小范围内
- 对
const
声明的引用类型变量,注意修改其属性和重新赋值的区别 - 警惕变量提升和暂时性死区可能导致的逻辑错误
合理使用这三个关键字可以显著提升代码的可读性和健壮性,减少变量作用域和赋值相关的bug,是现代JavaScript开发的重要基础。