前端进阶之旅前端进阶之旅
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片
  • 场景篇按分类整理的大前端场景考点
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
  • 动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
  • AI 助手随时提问,即时解析
  • AI 模拟面试模拟真实面试 + 报告
  • AI 知识地图串起全站知识点
  • AI 定制路线按你的简历现排
AI 热点
旧版
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片
  • 场景篇按分类整理的大前端场景考点
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
  • 动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
  • AI 助手随时提问,即时解析
  • AI 模拟面试模拟真实面试 + 报告
  • AI 知识地图串起全站知识点
  • AI 定制路线按你的简历现排
AI 热点
旧版
首页程序员面试题库可选链 ?. 与 && 短路的区别
JavaScript对象与原型

可选链 ?. 和用 && 一层层判断,有什么不一样?

?. 只认 null 和 undefined,左边是这两个值就停下并返回 undefined。&& 认的是所有假值,遇到 0、空字符串、false 也会停下,而且返回的是那个假值本身。所以取的值可能是 0 或空字符串时,用 && 会出错。

前端进阶之旅 · 一题精讲更新于 2026.09.29
JavaScript#对象与原型
先看核心答案读代码示例
理解线索

两种写法停下的条件不同

  1. ?.左边是 null 或 undefined 才停,结果固定是 undefined
  2. &&左边是假值就停,结果是那个假值,可能是 0、'' 或 null
  3. 短路范围a?.b.c.d 里 a 为空时,.b.c.d 全部跳过,不会报错

?. 不是万能的安全访问。a?.b.c 只保护了 a,如果 a 存在而 a.b 是 undefined,读 .c 照样报 TypeError。

核心回答

先记住这个答案

两者都能防止「读 undefined 的属性」报错,但停下的条件不一样。?. 只在左边是 null 或 undefined 时短路,返回 undefined;&& 遇到任何假值都会停,并把这个假值原样返回。所以当数据可能是 0、空字符串、false 时,&& 会把合法值当成「不存在」。另外 ?. 一旦短路,后面整条链都不再执行,写法也比 a && a.b && a.b.c 短得多。

  • ?. 只在空值时短路
  • && 遇到任何假值都停,并返回这个假值
  • 一处短路,后面整条链都不再执行
  • 调方法用 fn?.(),取下标用 arr?.[0]

差别出在假值上

平时对象都存在时,两种写法结果一样。差别只在左边是假值、但又不是 null 或 undefined 的时候才显现,比如 0、''、false。

同一个数据,两种写法JavaScript
const user = { name: '', tags: [] }
console.log(JSON.stringify(user.name && user.name.length)) // name 是空串,&& 直接返回 ''
console.log(user.name?.length) // 空串不是 null,照常读 length

const guest = null
console.log(guest && guest.profile.name) // 返回左边的 null
console.log(guest?.profile.name) // 统一返回 undefined

console.log(user.getName?.()) // 方法不存在也不报错
查看输出与解释
""
0
null
undefined
undefined

第一组最能说明问题。用户名是空字符串,想拿它的长度,正确答案是 0。&& 看到 '' 是假值就停下了,把 '' 返回出去;?. 只关心 '' 是不是 null 或 undefined,不是,就继续读 length。 第二组看返回值:&& 返回的是左边那个值,可能是 null,也可能是 0 或 false,类型不固定;?. 短路后永远是 undefined。后面接 ?? 给默认值时,?. 的结果更好处理。

整条链短路是什么意思

guest?.profile.name 里,只有 guest 后面写了 ?.,.profile 前面的点是普通的点。按直觉,guest?.profile 得到 undefined,再读 .name 应该报错才对,为什么没报?

因为 ?. 短路的是它后面的整条链,一直到这个表达式结束。guest 为空,.profile.name 全都跳过,整体结果直接是 undefined。这也意味着你不需要写成 guest?.profile?.name,除非 profile 本身也可能为空。

短路也会跳过函数调用和参数计算
obj?.method(sideEffect()) 里,obj 为空时 sideEffect() 根本不会执行。a?.[i++] 里,a 为空时 i 也不会加 1。这和 && 一样,右边不需要算就不算。 但短路只管到这个表达式的边界。(a?.b).c 加了括号,括号就是边界,a 为空时括号里得到 undefined,再读 .c 就会报错。
回答前,多想一步

容易答错的地方

以为 a?.b.c 每一层都受保护
?. 只保护紧挨着它的左边那个值。a 存在、a.b 是 undefined 时,a?.b.c 还是会报 TypeError。哪一层可能为空,就在哪一层后面加 ?.。
以为 fn?.() 能防住「不是函数」
fn?.() 只在 fn 是 null 或 undefined 时跳过调用。如果 fn 是个字符串或数字,照样会报 fn is not a function。
满屏都写 ?.
每个点都加 ?. 会把本该暴露的 bug 藏起来。比如接口约定 data.list 一定存在,结果后端漏传了,用 ?. 只会让列表静默显示为空,排查更难。只在业务上确实允许缺失的地方用。
试着用自己的话回答

面试官还会怎么问?

?. 能用在赋值左边吗?

不能。obj?.name = 'x' 是语法错误,可选链只能用来读,不能用来写。要写入就先判断对象存在,再赋值。

?. 和 ?? 怎么配合?

?? 是空值合并,同样只在左边是 null 或 undefined 时取右边的值。两者规则一致,常一起用:const size = config?.page?.size ?? 20。如果这里用 ||,size 为 0 时也会被替换成 20。

new 和标签模板能配合可选链吗?

不能。new a?.b() 是语法错误,把可选链用作标签模板的标签,也就是 a?.b 后面直接跟模板字符串,同样是语法错误。另外,delete a?.b 是允许的,a 为空时什么都不做,返回 true。

从一道题,走向一组知识

把知识连起来

对象与原型

对象里的数字键,遍历出来为什么总排在最前面?

可选链解决的是读属性不报错,属性按什么顺序被遍历出来则要看那篇的枚举规则。

对象与原型

用 defineProperty 写 getter/setter,和直接在字面量里写 get/set 有什么不一样?

obj?.prop 读到 getter 属性时照样会执行 getter,getter 怎么定义在那篇讲。

参考资料

  • JavaScript:对象与原型参考资料

示例用于理解所注明的运行环境与边界;延伸学习可结合原文中的更多案例。

本题目录
  1. 先记住这个答案
  2. 差别出在假值上
  3. 整条链短路是什么意思
  4. 容易答错的地方
  5. 面试官还会怎么问
  6. 把知识连起来
读懂,再试着讲出来

先看核心答案,再读代码。最后展开追问,检查自己有没有遗漏边界。

试着回答追问
浏览全部面试题理解原理,也关注真实的使用场景。回到顶部 ↑