← 返回文章列表
JavaScript·469 次阅读

可选链与空值合并:告别 && 地狱

可选链与空值合并:告别 && 地狱

ES2020 里我最喜欢的两个语法:可选链 ?. 和空值合并 ??。它们不引入新概念,只是把两个最常见的防御性写法变成了一等公民。

?.:深层取值不再叠 &&

以前从接口数据里取深层字段:

const city = data && data.user && data.user.address && data.user.address.city

现在:

const city = data?.user?.address?.city

中间任何一环是 null 或 undefined,整个表达式短路返回 undefined,不再层层判断。

还支持两种变体:

// 数组/动态键
const first = list?.[0]
const val = obj?.[key]

// 方法调用(方法不存在时不调用,返回 undefined)
obj.onChange?.(value)

obj.method?.() 这个写法在调可选回调时特别好用,以前要写 if (obj.onChange) obj.onChange(v)。

注意:短路不是万能的

// 前面用了 ?. 后面又裸取属性,照样可能炸
const len = data?.user.name // data 是 null 时 -> TypeError

// 正确:链条不能断
const len2 = data?.user?.name

还有一个容易忽略的:?. 只对 null 和 undefined 短路。如果中间值是 0、'' 这种 falsy 但不是空值的,会继续往下走然后报 TypeError——这其实是正确行为,真遇到了说明数据结构本身有问题。

??:只把 null/undefined 当"空"

以前给默认值:

const count = input.count || 10

问题来了:count 是 0 的时候,|| 也会判定为"空",返回 10——但 0 明明是个合法值!空字符串、false 同理。

?? 只在左边是 null 或 undefined 时才用右边的默认值:

const count = input.count ?? 10 // count = 0 时,结果正确为 0
const text = input.text ?? '默认' // text = '' 时保留 ''

黄金搭档

const pageSize = config?.pagination?.pageSize ?? 20

这一行覆盖了过去四五行的防御代码,而且语义更精确。

改写老代码的原则

  • a && a.b && a.b.c 这种纯防御空值的链,放心改 a?.b?.c
  • x || default 别盲目改 ??:先想清楚 falsy 值(0、''、false)是不是合法输入。配置项、表单数字通常该改;而"空字符串也视为未填"的场景保留 || 反而对
  • ?.() 调回调很香,但别在需要明确报错的地方用它掩盖 bug

兼容性

2020 年的新语法,现代浏览器和 Node 14+ 都支持,Babel/TS 也能转译。唯一的成本是团队约定:改就统一改,别一半 ?. 一半 && 混着写。

看到这里了?如果这篇文章帮到过你

请我喝瓶可乐就好 🥤

收款码

评论0 条

还没有评论,来抢沙发~

发表评论

评论需审核后显示

© 2026 许冬博客 · 专注 JS 技术分享

·RSS 订阅·Powered by Nuxt 4