javascript函数默认参数在每次调用时、函数体执行前于定义时的词法作用域中动态求值;仅当实参为undefined(或不传)时启用;支持闭包变量引用和参数间依赖(从左到右),但受tdz限制;默认表达式含副作用会重复执行。

JavaScript 函数的默认参数**不是在函数定义时计算,而是在每次调用时、函数体执行前、在函数自身的词法作用域中动态求值**。这个时机和作用域规则直接影响行为是否符合预期,尤其在涉及外部变量、其他参数或副作用时。
默认值只在实参为 undefined(或不传)时触发
只有当对应位置的实参严格等于 undefined(包括完全不传),才会启用默认值。其他 falsy 值如 null、0、false、空字符串等,都不会触发:
function fn(x = 'default') { return x; }-
fn()→'default' -
fn(undefined)→'default' -
fn(null)→null -
fn(0)→0
默认值表达式在调用时求值,且作用域是函数定义时的外层环境
默认值里的变量引用,查找的是**函数定义所在的作用域**(即闭包捕获的环境),不是调用时的作用域,也不包含后续声明的参数:
-
const outer = 'hello'; function f(a = outer + '!') { return a; }→ 每次调用都读取当前outer的值 -
function g(a = 1, b = a + 1) { return [a, b]; }→g()返回[1, 2](合法,b 可访问已初始化的 a) -
function h(a = b, b = 2) { }→ 报ReferenceError(a 无法访问尚未初始化的 b)
参数默认值会创建独立作用域,存在暂时性死区(TDZ)
一旦参数列表中出现默认值,整个参数部分会形成一个临时作用域。在这个作用域内,参数按从左到右顺序初始化;若某参数默认值试图引用自身或右侧未初始化的参数,就会触发 TDZ 错误:
-
function foo(x = x) { }→ReferenceError(相当于let x = x) -
var x = 1; function bar(y = x) { console.log(y); }→bar()输出1(y 引用的是外层var x) -
function baz(y = x) { let x = 2; }→ReferenceError: x is not defined(参数作用域中无x,不向外层块级作用域穿透)
默认值可含副作用,且每次调用都重新执行
如果默认值是函数调用、对象字面量或带状态的操作,它会在**每次调用未提供该参数时重复发生**,这既是灵活性来源,也是常见陷阱:
-
function log(x = console.log('default used')) { }→ 每次log()都打印一次 -
function getConfig(opts = { time: Date.now() }) { return opts; }→ 每次不传opts,都得到新时间戳的对象 -
function bad(arr = []) { arr.push(1); return arr; }→ 多次调用返回[1]、[1,1]…(因为每次都是新数组,实际不会共享;但若写成arr = sharedArr就会意外共享)
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











