标准答案

  1. 可选链 ?. 用来安全访问可能为空的对象链路。左侧是 null 或 undefined 时会短路返回 undefined,避免读取属性时报 Cannot read properties of undefined。
  2. 空值合并 ?? 只在左侧是 null 或 undefined 时使用右侧默认值。0、false、空字符串都不会触发默认值。
  3. 逻辑或 || 会在左侧是任意 falsy 值时使用右侧默认值,包括 0、false、空字符串、NaN、null、undefined。
  4. 业务里如果 0、false、空字符串是合法值,默认值应该优先用 ??。?. 适合访问可选链路,但不应该用来掩盖本来必须存在的数据结构错误。

题目解析

分页 page=0、开关 enabled=false、输入值为空字符串,都是 || 容易误伤的场景。?? 更符合“只在没有值时才给默认值”的业务语义。

?. 可以用于属性访问、方法调用和数组下标访问,例如 user?.profile?.name、handler?.()、list?.[0]。如果链路前半段为空,后面的表达式不会继续求值。

?? 不能直接和 ||、&& 混写而不加括号。加括号能让默认值逻辑更清楚,也能避开语法限制。

代码示例

下面示例展示 || 会覆盖合法 falsy 值,而 ?? 会保留这些业务值。

JavaScript
const query = {
  page: 0,
  keyword: '',
  exact: false
}

query.page || 1 // 1,0 被误认为没有值
query.page ?? 1 // 0

query.keyword || 'all' // 'all',空字符串被覆盖
query.keyword ?? 'all' // ''

query.exact || true // true,false 被覆盖
query.exact ?? true // false

const user = null
const city = user?.address?.city

const handler = undefined
handler?.(query)

常见误区

  • 用 || 给所有字段设默认值,导致合法的 0 或 false 被覆盖。
  • 以为 ?. 会捕获所有异常。它只处理 null/undefined 链路。
  • 混用 ?? 和 || 时不加括号,触发语法限制或可读性问题。

作者信息