let/const变量在声明前访问必报ReferenceError,因TDZ机制使变量从作用域入口即存在但禁止读写;应前置声明、避免条件内声明、禁用typeof检测、注意参数默认值顺序,并优先使用const。

直接在声明前访问 let 或 const 变量,一定会触发 ReferenceError —— 这不是 bug,是设计使然。暂时性死区(TDZ)的本质,是让变量从作用域入口开始就“存在”,但直到声明语句执行前都禁止读写。避开它,关键不是绕开规则,而是顺应机制。
把声明放在作用域最上方
这是最简单也最有效的习惯。只要确保每个 let 和 const 变量都在首次使用之前完成声明,TDZ 就不会被触碰。
- 函数内所有变量统一提到函数体开头
- 块级结构(如 if、for、{})中,声明紧贴左花括号下一行
- 避免在条件分支里“按需声明”,比如不要写
if (x) { let a = 1; console.log(a); },而应提前声明let a;,再在分支中赋值
别在 TDZ 里用 typeof 或 void 检测
很多人想用 typeof b 来安全判断变量是否存在,但对 let/const 来说,这依然会报错。TDZ 不区分操作类型,任何访问都会中断执行。
-
var下typeof undeclaredVar返回"undefined",但let b在声明前执行typeof b直接抛错 - 需要做存在性判断时,优先考虑是否真有必要——多数情况应靠代码结构保证变量已声明
- 若必须动态判断,可改用对象属性检测:
if ('prop' in obj)或obj.hasOwnProperty('prop')
警惕函数参数与默认值里的 TDZ
函数参数本身也受 TDZ 约束,尤其在设置默认值时容易中招:
- 错误写法:
function fn(x = y, y = 1) { }——x默认值中引用了尚未初始化的y,报错 - 正确顺序:
function fn(y = 1, x = y) { },确保依赖项先声明 - 参数默认值表达式中,不能引用后续参数,也不能引用函数体内的 let/const 变量
用 const 优先,减少重赋值需求
大多数变量其实不需要重新赋值。用 const 声明后,不仅避开 TDZ 引发的逻辑混乱,还能让意图更清晰。
- 基础类型(字符串、数字、布尔)和对象引用都可用
const,只要不重新指向新内存地址 - 对象属性仍可修改:
const user = { name: 'A' }; user.name = 'B';合法 - 只有真正需要变更绑定时才用
let,比如循环计数器、状态暂存等
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











