函数参数默认值创建独立的“参数作用域”,其变量查找遵循词法作用域、参数间不可互引、函数体内let/const声明引发TDZ三原则。

函数参数默认值会触发一个临时的、独立的作用域,它既不是函数体内部作用域,也不是外层作用域,而是在参数初始化阶段单独创建的“参数作用域”。识别它对变量查找的影响,关键看三点:默认值表达式中变量能否访问外层变量、能否访问同级其他参数、以及是否受函数体内后续声明干扰。
看默认值能否读取外层变量
默认值表达式中的变量引用,查找路径是函数定义时所在的作用域(即词法作用域),不是调用时的作用域。只要变量在函数定义位置的上层存在,就能被读到。
- 能访问:let x = 100; function f(y = x) { return y; } f() → 100
- 不能访问:function f(y = x) { let x = 200; return y; } f() → ReferenceError(x 在参数作用域中未声明)
看参数之间能否互相引用
带默认值的参数彼此不构成作用域链。前面的参数不能在后面参数的默认值中直接使用,除非它已出现在前面且无默认值;但后面参数的默认值也不能反向引用前面带默认值的参数。
- 合法:function f(a, b = a + 1) { return [a, b]; } f(5) → [5, 6]
- 报错:function f(a = b, b = 2) { } → ReferenceError(a 尝试读取尚未初始化的 b)
看函数体内同名声明是否干扰参数默认值
函数体内的 let/const 声明不会覆盖参数作用域里的变量查找,但会引发 TDZ(暂时性死区)问题——如果默认值表达式里用了同名变量,而函数体内又用 let 声明了它,那默认值求值时就会出错。
- 安全:let x = 1; function f(y = x) { var x = 2; return y; } f() → 1(var 声明被忽略,不影响参数作用域)
- 报错:let x = 1; function f(y = x) { let x = 2; return y; } f() → ReferenceError(y = x 触发时,x 在当前块中处于 TDZ)
验证方法:观察调用时行为而非定义时
参数作用域只在每次调用时才激活,且仅用于求值默认值。它不保留、不暴露、也不影响函数体执行。最直接的验证方式是:
- 传 undefined 或不传参,看默认值是否生效;
- 传 null、0、false 等 falsy 值,确认它们不触发默认值;
- 在默认值里放一个有副作用的表达式(如 console.log('init')),多次调用看是否重复执行。

















