暂时性死区(TDZ)指let/const变量在词法作用域内从起始到声明语句执行前的不可访问区间,期间任何读写(含typeof)均抛出ReferenceError;它以变量提升为前提,仅约束初始化前的访问。

暂时性死区(Temporal Dead Zone,简称 TDZ)不是变量“没声明”,而是变量“已存在但不能用”。它只影响 let 和 const 声明的变量,核心在于:一进入作用域,变量就已被引擎创建,但必须等到声明语句执行完成,才能读写——中间这段不可访问的区间,就是 TDZ。
TDZ 出现在哪里?
只要代码块中用了 let 或 const,该块的顶部到其声明语句之间,就自动形成 TDZ。这个块可以是:
- 函数体内部(整个函数作用域)
-
{}包裹的任意块级作用域(比如if、for、switch中的花括号) - 模块顶层(ESM 模块的全局作用域)
- 函数参数列表(参数默认值表达式中,对后续参数的引用)
为什么 typeof 也会报错?
在 var 时代,typeof undeclaredVar 返回 "undefined" 是安全的;但 TDZ 下,连 typeof 都被禁止:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
-
console.log(typeof a); let a;→ReferenceError - 因为
typeof本质仍是“访问变量”,而 TDZ 的设计原则是:未初始化前,任何访问都不允许 - 这和
var提升后默认为undefined有根本区别——let/const不提供兜底值
TDZ 和变量提升矛盾吗?
不矛盾。TDZ 正是以“提升存在”为前提的约束机制:
立即学习“Java免费学习笔记(深入)”;
- let/const 确实会提升声明:引擎在词法环境创建时就登记了变量名
-
但不提升初始化:赋值动作(
=右侧表达式)仍按代码顺序执行 - 所以 TDZ 是“已声明 + 未初始化”状态下的访问禁令,而非“未声明”
- 对比
console.log(b); var b = 1输出undefined,说明var提升并初始化了;而let只提升,不初始化
实际开发中怎么避开 TDZ?
关键不是“记住规则”,而是养成符合 TDZ 逻辑的书写习惯:
- 把 let/const 声明尽量放在块的开头,尤其在函数或 if 块内
- 避免在参数默认值里引用尚未声明的同级参数:
function f(x = y, y = 1) {}中x的默认值会触发 TDZ - 解构赋值时注意顺序:
let [a, b] = [1, 2]; console.log(a, b);没问题,但console.log(a); let [a] = [1];就会报错 - 循环中声明变量要小心:
for (let i = 0; i console.log(i), 0); }每次迭代都有独立 TDZ,这是闭包正确性的基础

















