该错误属于执行阶段,因为let变量在语法解析时已完成声明绑定,但访问时处于暂时性死区(TDZ)——已绑定未初始化,引擎在运行到console.log等语句时才抛出ReferenceError。

这个错误属于执行阶段,不是语法解析或编译阶段。
为什么是执行阶段而不是语法错误
JavaScript 引擎在词法分析和语法解析时,已经识别并登记了 let 变量的声明(即完成“绑定”),代码能顺利通过语法检查、进入执行流程。报错发生在实际运行到访问语句(比如 console.log(a))那一行时——此时变量虽已绑定,但尚未初始化,引擎检测到访问处于暂时性死区(TDZ),立刻抛出 ReferenceError。
TDZ 报错的关键特征
- 代码可以正常解析,也能开始执行(例如函数已调用、脚本已加载)
- 错误只在“读取/写入/甚至
typeof检测”该变量的瞬间触发 - 不是
SyntaxError,无法通过 ESLint 等静态工具提前捕获 - 与
var的“提升后值为undefined”形成对比:let是明确拒绝访问,而非返回默认值
典型触发场景
以下代码都会在执行到 console.log(x) 时抛错:
Java项目代码review工具。分析Git变更+完整调用链路上下文,推断业务需求,进行多维度评分和分类汇总,生成完整PRD文档。包含细粒度Java代码审查清单(Null安全、异常处理、Streams、并发、equals/hashCode、资源管理、API设计、性能、MyBatis/ORM、事务边界、SQL/DD...
-
console.log(x); let x = 1;(顶层作用域) -
function foo() { console.log(y); let y = 2; }(函数作用域内) -
if (true) { console.log(z); let z = 3; }(块级作用域内)
和 var 的根本区别
var 声明在变量环境(Variable Environment)中一步完成“声明 + 初始化为 undefined”,所以访问不会报错;而 let 在词法环境(Lexical Environment)中分两步:先绑定(binding)、后初始化(initialization)。中间那段“已绑定未初始化”的区间就是 TDZ,它的约束只在运行时生效。
立即学习“Java免费学习笔记(深入)”;

















