const 禁止重新赋值绑定但允许修改对象内部状态,let 可重新赋值;两者均为块级作用域、存在暂时性死区、不可重复声明,且不挂载到 window。

let 和 const 的核心区别不是“能不能改值”,而是“能不能重新赋值绑定”——const 禁止对变量标识符做第二次赋值,但不阻止修改其指向的可变对象内部状态。
作用域完全一致,但声明后行为截然不同
两者都是块级作用域({...} 内有效),不会像 var 那样泄漏到外层或函数顶部。真正差异在初始化和后续操作:
-
let声明后可随时重新赋值:let count = 1; count = 2; -
const必须在声明时初始化,且之后不能用=赋新值:const PI = 3.14159; PI = 3.14;→ 报错Assignment to constant variable. - 两者都存在暂时性死区(TDZ):在声明语句前访问会抛
ReferenceError,不是undefined
const 声明的对象/数组能改内容,但不能换引用
这是最常被误解的一点:const 锁的是“绑定关系”,不是“值的不可变性”。
-
const arr = [1, 2]; arr.push(3);✅ 合法 —— 数组本身没被替换,只是内部变了 -
arr = [4, 5];❌ 报错 —— 尝试把arr指向一个新数组 -
const obj = { a: 1 }; obj.a = 2;✅ 合法;obj = {};❌ 报错 - 如需真正不可变,得用
Object.freeze()或结构克隆,const不负责这个
什么时候该用 let,什么时候必须用 const
这不是风格偏好,而是语义约束:用 const 是默认选项,只有明确需要重赋值时才退化为 let。
立即学习“Java免费学习笔记(深入)”;
- 函数参数、循环变量(
for (const item of list))、配置项、API URL、正则表达式等 —— 全部优先const - 计数器、临时中间值、状态标志(如
let isLoading = true)、需要多次更新的 DOM 引用 —— 用let - 重复声明同名变量:两者都不允许,
let x; let x;和const y = 1; const y = 2;都是SyntaxError - 全局污染风险:两者都不会挂载到
window(不像var),这点安全一致
常见报错与调试线索
遇到运行时报错,先看错误类型再定位:
-
ReferenceError: Cannot access 'x' before initialization→ TDZ,检查是否在let/const声明前读取了变量 -
TypeError: Assignment to constant variable→ 试图给const变量重新赋值,注意箭头函数参数、解构赋值左侧也受此约束 -
SyntaxError: Missing initializer in const declaration→const没有初始值,哪怕写const x = null;也比空着强 - 在
for循环中误用var导致闭包问题?直接换成for (const item of arr)或for (let i = 0; ...)即可规避
真正容易被忽略的点是:const 对函数表达式、类声明、模块导入(import)同样适用,它们天然就是“只读绑定”——这恰恰是现代 JS 编码稳定性的底层支撑。











