可选链操作符?.用于安全访问嵌套属性或调用方法,遇null/undefined立即返回undefined而不报错;需与空值合并操作符??配合使用以提供默认值,且仅适用于属性访问、函数调用和动态键访问,不支持数组索引语法。

可选链操作符 ?. 能避免 Cannot read property 'x' of undefined
当访问深层嵌套对象属性时,传统写法要层层判断 obj && obj.a && obj.a.b && obj.a.b.c,既啰嗦又易漏。用 ?. 后,只要链中任意一环是 null 或 undefined,整个表达式立即返回 undefined,不再报错。
常见误用场景:
- 从 API 响应中取
response.data.user.profile.name,但profile可能为空 - 处理表单字段
form?.values?.email,其中form或values尚未初始化
注意:它只对「对象属性访问」和「函数调用」有效,不能用于数组索引(arr?[0] ❌),数组要用 arr?.[0](带方括号)。
?. 和 ?? 组合使用才是完整安全链
?. 解决“访问途中崩”,?? 解决“最终值为空”。两者配合才能覆盖全部空值路径。
立即学习“Java免费学习笔记(深入)”;
比如想取用户邮箱,但允许 fallback 到默认值:
const email = user?.contact?.email ?? 'no-email@example.com';
如果只用 ?.,结果可能是 undefined;只用 ??,前面链式访问仍可能抛错。必须先用 ?. 安全取值,再用 ?? 提供兜底。
容易踩的坑:
-
obj?.a?.b() ?? 'default':函数调用后返回undefined,??才生效;但如果b本身不存在,?.已截断,不会报错 -
obj?.a.b中,若a是null,整个表达式为undefined;但若a是原始值(如字符串),a.b会是undefined(不报错),这属于 JS 原有行为,?.不改变这点
函数调用和动态属性也要加 ?.
可选链不仅适用于点号访问,还支持函数调用 obj?.method?.() 和动态键访问 obj?.[key]。
典型用例:
- 不确定方法是否存在:
logger?.debug?.('msg'),避免logger.debug is not a function - 根据变量名取属性:
data?.[fieldPath]?.toString(),其中fieldPath可能为undefined - 链式调用后继续访问:
arr?.[0]?.name?.toUpperCase?.(),每一步都可中断
注意:obj?.method() 中,如果 method 存在但返回 undefined,后续链不会中断——?. 只检查「调用目标是否存在」,不检查「返回值是否为空」。
兼容性与编译配置别漏掉
?. 是 ES2020 特性,Chrome 80+、Firefox 74+、Safari 13.1+ 原生支持。但如果你用 Webpack/Babel,需确认:
- Babel 需启用
@babel/plugin-proposal-optional-chaining插件 - TypeScript 用户:TS 3.7+ 默认支持,但
target设为ES2019或更低时,会自动降级为三元判断(可能略臃肿) - 旧版 Node(如 v12)需开启
--harmony-optional-chaining标志(不推荐生产用)
真正容易被忽略的是:某些 Linter(如 ESLint 的 no-unused-expressions)可能误报 obj?.a 为无用表达式,需升级插件或关闭该规则。











