javascript前端开发语言

可选链 ?.: 什么时候该用,什么时候别用

用属性访问、数组索引和函数调用三个场景讲清 JavaScript 可选链 `?.` 的行为,并解释它与空值合并、逻辑或和错误兜底之间的边界。

·更新于 ·阅读约 6 分钟·计算中...
可选链 ?.: 什么时候该用,什么时候别用

可选链 ?. 解决的不是“任何报错都别抛”,而是“当中间某一段可能是 nullundefined 时,不要因为继续取属性或调用方法而直接炸掉”。它非常适合处理后端返回、可选回调、可选配置,但如果你把它到处滥用,也会把真正应该暴露的错误吞掉。

目录

基本行为

object?.property
object?.[index]
object?.method?.()

规则很简单:

  • 如果左边是 nullundefined,表达式直接返回 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

差异在于:

  • ||:左边只要是假值就走右边
  • ??:左边只有 nullundefined 才走右边

可选链和空值合并是一组很常见的搭配。

什么时候不该用

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 数组与遍历指南

结论

  • 可选链解决的是“空值链路访问”问题。
  • 它最适合可选对象、可选回调和接口返回数据。
  • 它应该和 ?? 配合得比和 || 更频繁。
  • 不要用它掩盖本该暴露出来的数据结构错误。
3 分钟

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 软件评测、可信来源更新、替代方案和少折腾指南。