可选链 ?. 解决的不是“任何报错都别抛”,而是“当中间某一段可能是 null 或 undefined 时,不要因为继续取属性或调用方法而直接炸掉”。它非常适合处理后端返回、可选回调、可选配置,但如果你把它到处滥用,也会把真正应该暴露的错误吞掉。
目录
基本行为
object?.property
object?.[index]
object?.method?.()
规则很简单:
- 如果左边是
null或undefined,表达式直接返回undefined - 否则继续正常访问
访问嵌套属性
const user = {
profile: {
city: "Hangzhou",
},
}
user?.profile?.city // "Hangzhou"
user?.profile?.zipCode // undefined
它能替代这类老写法:
user && user.profile && user.profile.city
代码会短很多,也更不容易把真假值判断和空值判断混在一起。
安全调用方法
onSuccess?.(result)
这在 React props、插件回调、可选 hooks 里很常见。你不需要先写:
if (onSuccess) {
onSuccess(result)
}
但要注意:如果 onSuccess 存在却不是函数,仍然可能出错。可选链不是类型系统。
数组和索引访问
items?.[0]
response?.data?.[0]?.id
它适合处理数组是否存在、接口数据是否为空这种场景,但“索引越界”本身不会抛错,本来就会得到 undefined。真正需要可选链的是数组本身可能不存在。
和 || 的区别:默认值别乱给
很多人会这样写:
const count = user?.count || 0
这在 count = 0 时也会落到默认值,因为 0 是 falsy。更稳的写法通常是空值合并:
const count = user?.count ?? 0
差异在于:
||:左边只要是假值就走右边??:左边只有null或undefined才走右边
可选链和空值合并是一组很常见的搭配。
什么时候不该用
1. 不该把确定存在的对象也写成可选
config?.apiBaseUrl
如果 config 在设计上就是必须存在,这样写会把真正的初始化错误悄悄吞掉。你最后看到的只是后面某处 undefined 带来的二次问题。
2. 不该把所有链路都写成 ?.
app?.store?.user?.profile?.settings?.theme
这种代码表面安全,实际是在告诉读代码的人:我也不确定这里到底应该有哪些对象存在。通常更好的做法是尽早收敛数据边界。
3. 不要把它当成顶级未声明变量保护
?. 不能拯救一个根本没声明的标识符:
foo?.bar
如果 foo 压根没定义,仍然会报 ReferenceError。它只处理“值为空”,不处理“变量不存在”。
一个更贴近真实开发的例子
const avatarUrl =
response?.data?.user?.avatar?.url ?? "/images/default-avatar.png"
这里:
?.负责安全穿过不确定层级??负责只在空值时给默认图
如果你经常处理对象展开、浅拷贝和默认值覆盖,也可以顺着看 JavaScript 对象复制指南 和 JavaScript 数组与遍历指南。
结论
- 可选链解决的是“空值链路访问”问题。
- 它最适合可选对象、可选回调和接口返回数据。
- 它应该和
??配合得比和||更频繁。 - 不要用它掩盖本该暴露出来的数据结构错误。
继续阅读
console.dir 和 console.log 有什么区别
说明 console.log 与 console.dir 在浏览器 DevTools 里的实际差异,重点回答对象调试、DOM 节点查看和 Node.js 环境下什么时候该用哪一个。
18 分钟理解与掌控副作用:前端开发(Vue 3 和 React)中的关键环节
在现代前端开发中,副作用(Side Effects)是一个经常被提到的概念。它指的是那些在执行计算或操作时,不仅影响当前函数的输出,还可能对外部世界产生某些影响的操作。常见的副作用包括:数据请求、事件监听、定时器、DOM 操作等。处理副作用是前端开发中非常重要的一部分,尤其是在构
9 分钟for 循环里 var 和 let 为什么结果不同
用经典的 `for` 循环闭包例子解释为什么 `var` 会得到 `3 3 3`,而 `let` 会得到 `0 1 2`,并说明函数作用域、块级作用域和 IIFE 在这里分别扮演什么角色。
订阅 FreeMac
每周精选:免费 Mac 软件评测、可信来源更新、替代方案和少折腾指南。