← 返回目录

6. 函数参数默认值

把函数想成一家餐厅的菜单:参数就是客人下单时给的选项。老规矩是客人没说就服务员自己猜(手写 if 判断);现在新规矩是菜单上直接印好"默认配餐"——客人没点的那一项自动上默认的。关键:只有客人真的没给(undefined)才上默认,给了 0、空字符串、false 也算点了单,不会被换掉。这比用 || 兜底安全得多。

6.1 互动演示

f(b = 10) 传参:
输入 0、1、空 分别试试,看默认值什么时候生效。

6.2 知识点讲解

① 基本对比:手动判断 vs 参数里直接写默认值

以前默认值要在函数体里写一行 if 判断,现在直接写在参数括号里,像菜单上印好。

// 以前:函数里手动判断"客人给没给"
function add(a, b, c) {            // 收三个参数
  if (c === undefined) c = 10; // 没给就补上 10
  return a + b + c;              // 三个数相加
}
console.log(add(1, 2)); // 13(c 没给,用了 10)

// 现在:直接写在参数 = 后面,菜单印好默认值
function add(a, b, c = 10) { // c 没传就自动是 10(写在括号里)
  return a + b + c;          // 不用再手写 if
}
console.log(add(1, 2)); // 13(c 自动用 10)
console.log(add(1, 2, 3)); // 6(传了 3,就用 3)

② 为什么不用 || 兜底(面试高频)

|| 是个"心软"的服务员:只要客人给的是 0、空串、false,它都当成"没点",硬塞默认值。而参数默认值只认 undefined

// || 的坑:0、""、false 都是"假值",会被误换成默认值
function f(a, b) {          // 普通函数
  b = b || 10; // 只要 b 是假值就换成 10
  return b;         // 把 b 返回
}
console.log(f(1, 0)); // 10(客人明明点了 0,被当成没点!)

// 参数默认值:只在 undefined 时才兜底
function f(a, b = 10) {     // 默认值写括号里,只认 undefined
  return b;                 // 直接返回 b
}
console.log(f(1, 0)); // 0(0 是客人真点的,保留)
console.log(f(1, undefined)); // 10(只有 undefined 才触发默认)

如果你以前用 b = b || 10 写兜底,业务里用户传 0 表示"不限制",结果被悄悄换成 10。这种 bug 特别隐蔽——所以参数默认值最大的价值就是:0、""、false 这种"有效但假"的值不会被误伤

③ 配合解构:拿不到属性也有兜底

实战里函数经常收一个"配置对象",这时候解构 + 默认值是最稳的组合。

// 以前:进去还得 obj.name 一个个判断
function fn(obj) {              // 收一个对象
  let name = obj.name || "未知"; // 没名字就写未知
  console.log(name);            // 打印出来
}

// 现在:参数直接解构,每个属性都能带默认值
function fn({ name = "未知" } = {}) { // 把对象拆成 name,没 name 就"未知";连对象都没传就用 {}
  //       ^^^^^^^^    整个参数都没传时,给个空对象兜底
  console.log(name);            // 直接用拆出来的 name
}
fn({}); // 未知(空对象里没 name)
fn({ name: "大喇叭" }); // 大喇叭(传了就用传的)
fn(); // 未知(连对象都没传,= {} 救了它)

注意 { name = "未知" } = {} 有两层兜底:= {} 是"客人连盘子都没端来时,自己塞个空盘子",name = "未知" 是"盘子里没这道菜时上默认"。两层各管各的,少写任何一层,调用 fn 都会报错。

6.3 实战:用在哪 / 常见坑 / 怎么解决

① 可能在什么地方用:封装可配置的工具函数(如 ajax(url, method = "GET"))、分页函数 getPage(page = 1, size = 10)、组件默认参数、解析接口返回时兜底字段。

② 常见的问题:|| 导致 0、"" 被覆盖;默认参数写在非最后位置调用时对不上;解构整个对象时漏写 = {},调用不传对象直接报"Cannot destructure property"。

③ 解决思路:要兜底就用参数默认值或 ??,别用 ||;有默认值的参数尽量放最后;解构对象参数一律写成 function fn({ x = 1 } = {}) 双兜底。

一句话:默认值写在参数 = 后面、只在 undefined 时生效;取"配置类"参数用 解构 + 默认值 组合最稳。