let 和 const 声明存在提升但不初始化,导致暂时性死区(tdz),在声明前访问会抛出 referenceerror;且二者为块级作用域,仅在最近的花括号内有效。

JavaScript 中使用 let 和 const 声明变量,本身就能天然避免传统 var 带来的“变量提升”(hoisting)问题——但更准确地说,它们不是“避免提升”,而是**存在提升但不初始化**,从而进入“暂时性死区”(TDZ)。理解这一点,才能真正写出安全、可预测的代码。
let 和 const 也会被提升,但不会被初始化
var 声明会被提升并初始化为 undefined,所以可以在声明前访问(尽管值是 undefined);而 let 和 const 虽然声明位置也被提升到块级作用域顶部,但引擎不会为其赋初始值。从作用域开始到声明语句执行前的这段区域,就是“暂时性死区”。在此区域内访问变量会直接抛出 ReferenceError。
-
console.log(a); let a = 1;→ 报错:ReferenceError: Cannot access 'a' before initialization -
console.log(b); const b = 2;→ 同样报错,const也受 TDZ 约束 - 这和
var的console.log(c); var c = 3;输出undefined形成鲜明对比
用块级作用域限制变量生命周期
let 和 const 是块级声明,只在最近的花括号 {} 内有效。这种作用域限制让变量“出现得晚、消失得早”,从源头上减少因提升导致的意外访问。
Java JDK 25 来自 OpenJDK 官方归档,版本为 JDK 25,本条下载地址已指向官方 Windows x64 zip 安装包直链,适合调试旧项目或兼容旧版 Java 运行环境。
- 在
if、for、while或任意{}中声明的let/const,外部无法访问 - 例如:
for (let i = 0; i → 报错,<code>i不在外部作用域 - 而
var i则会泄漏到函数或全局作用域,可能覆盖已有变量
const 并非“不可变”,而是“不可重新赋值”
很多人误以为 const 声明的是“常量值”,其实它保证的是“绑定不可变”:变量标识符不能再指向另一个内存地址。这对避免意外覆盖非常关键,尤其配合对象或数组时需注意:
-
const obj = { x: 1 }; obj.x = 2;✅ 允许(修改属性) -
obj = { y: 3 };❌ 报错(试图重新赋值) - 如需真正冻结内容,可配合
Object.freeze(),但仅限一层浅冻结
最佳实践建议
养成明确、保守的声明习惯,能最大程度规避 TDZ 和作用域混乱:
- 默认优先用
const;只有确认需要后续重新赋值时,才改用let - 始终在使用变量前声明,哪怕只是提前几行——不依赖 TDZ 的报错来“提醒”你
- 避免在条件块外引用块内
let/const变量,即使语法上看似可行(比如在函数表达式中闭包捕获) - 不用
var,除非维护非常老的代码且无法升级作用域规则
本质上,let 和 const 不是靠“不提升”来解决问题,而是用“提升但不初始化 + 块级作用域 + 明确赋值要求”构建了一套更严谨的变量管理机制。写代码时多一分声明意识,就少十分运行时意外。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










