应优先使用 const,其次 let,避免 var;const 表示绑定不可重赋而非值不可变,let 仅用于必然需重新赋值的场景如 for 循环计数器。

JavaScript 中变量声明的核心原则是:能用 const 就不用 let,能用 let 就不用 var。这不是教条,而是由作用域、可变性与调试体验共同决定的。
为什么 var 基本不该再用了
var 的函数作用域和变量提升(hoisting)容易引发隐蔽 bug。比如在 if 块中声明 var x = 1,x 依然可在块外访问;更糟的是,未赋值前读取会得 undefined 而非报错,掩盖逻辑错误。
现代代码中应完全避开 var,除非维护非常老的代码或刻意兼容 IE8 及更早版本(已无实际必要)。
let 和 const 的根本区别在「可重新赋值」而非「是否常量」
const 并不意味着「值不可变」,只表示「绑定不可重赋」。也就是说:
立即学习“Java免费学习笔记(深入)”;
-
const obj = { a: 1 }→ 合法:obj.a = 2;非法:obj = { b: 2 } -
const arr = [1]→ 合法:arr.push(2);非法:arr = [2] -
const fn = () => {}→ 合法:fn();非法:fn = null
真正需要「不可变值」时,应配合 Object.freeze() 或使用 Immutable.js 等库,而不是依赖 const。
什么时候必须用 let?
仅当变量在声明后**必然会被重新赋值**,且无法通过函数拆分或表达式重构避免时,才用 let:
- for 循环计数器:
for (let i = 0; i - 状态暂存(如累加、交换、条件分支中的不同值):
let result; if (x) result = a(); else result = b(); - 异步回调中需更新的引用(如取消定时器 ID):
let timerId; timerId = setTimeout(...); clearTimeout(timerId);
注意:如果只是临时中间值(如 let temp = x * 2),优先考虑直接内联或提取为独立函数,减少可变状态。
常见误用与调试线索
遇到 ReferenceError: Cannot access 'xxx' before initialization,基本是因为在 const/let 声明前就访问了变量——这是「暂时性死区」(TDZ)的明确信号,说明你试图绕过声明顺序,应检查逻辑流是否合理。
另一个典型问题是循环中闭包捕获了同一个 let 绑定(尤其用 var 时更严重)。ES6 中 let 在每次迭代中创建新绑定,但若用 setTimeout 异步读取循环变量,仍需确认是否真需要每个迭代的快照——有时 const + 箭头函数参数传入更清晰。
最易被忽略的一点:模块顶层的 const 和 let 不会挂到 window 上,而 var 会。如果你在浏览器控制台调试时发现变量“找不到”,先看是不是用了块级声明却误以为是全局变量。











