javascript函数参数默认值初始化时触发tdz,本质是默认值表达式求值中访问了尚未完成初始化的类let绑定;参数按从左到右顺序初始化,自身或右侧参数在未初始化前被引用即报错,仅typeof例外返回"undefined"。

JavaScript中函数参数默认值初始化时触发TDZ,本质不是参数本身“有TDZ”,而是默认值表达式在求值过程中,试图访问一个已声明但尚未完成初始化的let/const式绑定——而函数参数的初始化过程,恰好模拟了这种绑定行为。
参数初始化形成类let绑定的临时作用域
当函数定义含默认参数(如 a = 1),整个参数列表会创建一个独立初始化作用域。这个作用域按从左到右顺序依次为每个参数建立绑定:
- 先为第一个参数(如
x)创建绑定,进入“未初始化”状态(类似let x声明后、赋值前) - 再求值其默认值表达式;此时若表达式引用
x自身,就掉进它的TDZ - 该参数完成初始化后,才退出TDZ,后续参数的默认值才能安全引用它
典型触发场景:默认值里提前读取自身或右侧参数
以下写法都会报 ReferenceError: Cannot access '...' before initialization:
-
function f(x = x) {}——x在自己默认值中被读取,处于自身TDZ -
function f(x = y, y = 2) {}——x默认值依赖y,但y尚未初始化(绑定刚建立,赋值还没执行) -
function f({ a = b } = {}, b = 3) {}—— 解构默认值中的b引用,发生在b初始化之前
为什么 typeof 不报错?
这是唯一例外:typeof x 在参数TDZ内不会抛错,而是返回 "undefined"。这与块级TDZ中 typeof 的行为一致,属于语言特例,不能用来判断变量是否“可用”。
安全做法:把依赖逻辑移到函数体内
避免在默认值中做跨参数计算,改用显式赋值:
- 错误写法:
function g(a = 1, b = a + 1) { ... }(虽合法,但易引发理解偏差) - 推荐写法:
function g(a = 1, b) { b = b ?? a + 1; ... } - 更清晰:
function g(a = 1, b) { const finalB = b !== undefined ? b : a + 1; ... }
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











