JavaScript 变量声明:var vs let vs const详情
在 JavaScript 中,变量声明经历了从 var
到 let
/const
的演变。ES6(2015)引入的 let
和 const
解决了 var
的关键缺陷。接下来我们一起看看三者的区别。
一、核心区别速览
特性 | var | let | const |
---|---|---|---|
作用域 | 函数作用域 | 块级作用域 | 块级作用域 |
重复声明 | ✅ 允许 | ❌ 禁止 | ❌ 禁止 |
变量提升 | ✅ 提升 | ⚠️ 暂时性死区 | ⚠️ 暂时性死区 |
初始值 | 可不初始化 | 可不初始化 | ❌ 必须初始化 |
重新赋值 | ✅ 允许 | ✅ 允许 | ❌ 禁止 |
二、详解关键特性
-
作用域(Scope)
-
var
:函数作用域
仅在函数内部创建新作用域,在if
/for
等块中会泄漏到外部:function run() {if (true) {var x = 10;}console.log(x); // 10(泄漏到函数作用域) }
-
let
/const
:块级作用域
只在{}
块内有效:if (true) {let y = 20;const z = 30; } console.log(y); // ReferenceError console.log(z); // ReferenceError
-
-
重复声明
var
允许重复声明(易引发 bug):var a = 1; var a = 2; // 不报错
let
/const
禁止重复声明:let b = 5; let b = 10; // SyntaxError
-
变量提升(Hoisting)
var
提升且初始化为undefined
:console.log(c); // undefined var c = 15;
let
/const
存在暂时性死区(TDZ):
声明前访问会报错:console.log(d); // ReferenceError let d = 25;
-
常量性质
const
必须初始化且不能重新赋值:const PI = 3.14; PI = 3.14159; // TypeError
- 注意:
const
定义的对象/数组内容可修改(绑定关系不变):const user = { name: "Alice" }; user.name = "Bob"; // ✅ 允许 user = { name: "Eve" }; // ❌ TypeError(重新赋值)
三、最佳实践指南
-
默认使用
const
适用于所有不需要重新赋值的变量(避免意外修改)。const API_URL = "https://api.example.com"; const MAX_ITEMS = 100;
-
需要重新赋值时用
let
替代循环计数器等场景中的var
。for (let i = 0; i < 5; i++) {console.log(i); // i 只在循环块内有效 }
-
避免使用
var
除非维护旧代码,新项目优先使用块级作用域变量。 -
全局变量注意
var
在全局作用域会挂载到window
对象,let
/const
不会:var globalVar = "old"; let globalLet = "new"; console.log(window.globalVar); // "old" console.log(window.globalLet); // undefined
四、关键示例对比
// 作用域对比
function scopeTest() {if (true) {var varVar = "var";let letVar = "let";}console.log(varVar); // "var"(泄漏)console.log(letVar); // ReferenceError
}// 循环中的闭包问题(经典面试题)
for (var i = 0; i < 3; i++) {setTimeout(() => console.log(i), 100); // 输出 3, 3, 3
}for (let j = 0; j < 3; j++) {setTimeout(() => console.log(j), 100); // 输出 0, 1, 2
}
总结
var
:历史遗留,存在作用域泄漏和提升问题,现代开发中应避免。let
:块级作用域,需重新赋值时的首选(如循环计数器)。const
:块级作用域,声明常量或引用类型时的默认选择。
迁移建议:在新项目和 ES6+ 环境中全面采用
let
/const
,使用 linter 工具(如 ESLint)强制禁用var
。
通过理解这些差异,你可以减少变量相关 bug,写出更清晰、更稳定的 JavaScript 代码!