JavaScript中函数参数本身不触发TDZ,但默认值表达式引用未初始化的let/const变量会报错,因求值发生在参数初始化阶段,此时变量仍处于TDZ;安全做法是将依赖逻辑移至函数体内处理。

JavaScript中函数参数本身不会触发TDZ(暂时性死区),TDZ仅存在于let/const声明的块级作用域内,且只针对变量声明本身。函数参数的初始化过程不涉及TDZ机制,但容易混淆的场景常出现在参数默认值表达式中引用了后续声明的let/const变量。
参数默认值中访问尚未初始化的let/const变量
当函数使用默认参数,且默认值表达式里引用了当前作用域中用let或const声明但尚未执行到的变量时,会抛出ReferenceError——这看似像TDZ,实则是默认值表达式在参数初始化阶段求值,而此时let/const变量仍处于TDZ中。
示例:
function foo(x = y, y = 1) { // ❌ 报错:Cannot access 'y' before initialization
return [x, y];
}
foo();
原因:参数按从左到右顺序初始化;x的默认值依赖y,但y的声明虽已解析,其绑定尚未完成(let/const y = 1 还没执行),y处于TDZ,因此访问y报错。
参数默认值中解构赋值引发的TDZ误判
解构参数的默认值若含let/const声明,且右侧表达式提前引用该声明,也会触发TDZ错误。
立即学习“Java免费学习笔记(深入)”;
function bar({ x = y } = {}, y = 2) { // ❌ y在x默认值中被访问时仍处于TDZ
return x;
}
bar();
关键点:{ x = y } 是默认值的一部分,在参数初始化阶段求值;此时y虽在参数列表中,但尚未完成绑定,属于TDZ范围。
与var、function声明的区别(对比理解)
var和function声明存在变量提升且初始化为undefined,不会进入TDZ;而let/const参数默认值中若引用自身或其他let/const变量,则严格受限:
- var y = 1 在参数中不合法(参数不能用var声明)
- function参数列表中不能出现let/const声明语句,只能在函数体内部声明
- 真正触发TDZ的是“块级作用域内let/const声明之后、赋值之前”的访问行为,参数默认值求值恰好发生在这个时间窗口
安全写法建议
避免在默认参数中交叉引用,确保依赖关系单向、明确:
- 把复杂逻辑移到函数体内,用局部变量承接
- 默认值尽量使用字面量、函数调用或已确定存在的全局/外层变量
- 如需参数间依赖,改用单个对象参数并手动解构赋值
例如:
function baz(opts = {}) {
const { y = 1, x = y } = opts; // ✅ 在函数体内解构,y已初始化
return [x, y];
}
baz(); // [1, 1]










