
本文介绍如何结合可选链操作符(?.)与空值合并操作符(??)安全、简洁地访问嵌套 json 数据,避免因空数组、缺失属性或 undefined 导致的运行时错误。
本文介绍如何结合可选链操作符(?.)与空值合并操作符(??)安全、简洁地访问嵌套 json 数据,避免因空数组、缺失属性或 undefined 导致的运行时错误。
在现代 JavaScript 开发中,频繁处理深层嵌套的 API 响应(如 GraphQL 或 RESTful JSON)时,传统防御性判空(如 if (obj && obj.a && obj.a.b))不仅冗长,还容易遗漏边界情况——例如当 names 是一个空数组 [] 时,data?.body?.data?.names[0]?.firstName 会因尝试访问 [0] 而返回 undefined,但不会抛错;真正的问题在于:它无法区分“路径中途断开”和“值本身为 undefined”,更难以统一提供默认值。
✅ 正确解法:组合使用 ?. 与 ??
可选链 ?. 负责安全穿透可能为 null 或 undefined 的中间节点(包括对象属性、数组索引、函数调用),而空值合并 ?? 则在左侧表达式为 null 或 undefined 时提供兜底值。二者配合,可一行代码完成“安全取值 + 默认回退”。
以下为完整示例:
立即学习“Java免费学习笔记(深入)”;
const data = {
body: {
data: {
names: [
{ firstName: 'John' },
{ firstName: 'Johnn' }
]
}
}
};
// ✅ 安全获取首个 firstName,若任意环节缺失则返回 'Unknown'
const firstName = data?.body?.data?.names?.[0]?.firstName ?? 'Unknown';
console.log(firstName); // 'John'
// ✅ 即使 names 不存在、为空对象或为空数组,均不会报错
const dataWithoutNames = {
body: { data: {} }
};
const fallbackName = dataWithoutNames?.body?.data?.names?.[0]?.firstName ?? 'Unknown';
console.log(fallbackName); // 'Unknown'
// ✅ 空数组场景也适用(names: [] → [0] → undefined → 触发 ??)
const emptyNames = {
body: { data: { names: [] } }
};
const emptyResult = emptyNames?.body?.data?.names?.[0]?.firstName ?? 'No Name';
console.log(emptyResult); // 'No Name'⚠️ 注意事项:
- ?.[0] 中的方括号必须带 ?. 前缀,否则 names[0] 在 names === undefined 时会直接抛 TypeError: Cannot read property '0' of undefined;
- ?? 仅在左侧为 null 或 undefined 时生效,若值为 0、false、''(空字符串)等 falsy 值,不会触发默认值——这是其区别于 || 的关键优势;
- 若需兼容旧浏览器(如 IE),需通过 Babel 编译并启用 @babel/plugin-proposal-optional-chaining 和 @babel/plugin-proposal-nullish-coalescing-operator 插件。
? 总结:摒弃多层 && 判空或冗长 if 语句,优先采用 ?. + ?? 组合。它语义清晰、执行高效、可读性强,是 TypeScript 和现代 JavaScript 工程中处理不确定数据结构的推荐实践。










