可选链 `?.`——再也不用写一长串 `&&` 了!
“ 同事凑过来看了一眼:“你只检查了 我陷入了沉思:难道我要写 直到有一天,我发现了可选链操作符 在过去,为了安全地访问深层嵌套的属性,我们不得不写这样的代码: 如果中间任何一环是 更别提调用可能存在的方法: 万一 可选链操作符 就这么简单!如果 如果 如果 如果最终结果是 可选链是 ES2020 特性,现代浏览器都支持(Chrome 80+、Firefox 74+、Safari 13.1+)。如果需要兼容旧浏览器,可以用 Babel 插件 可选链操作符让 JavaScript 代码变得更加简洁、安全、可读。你不再需要写一长串 记住:用 每日一问:你曾经因为忘记检查深层属性,导致过线上报错吗?或者写过最长的 引言
Cannot read property 'name' of undefined——又是这个错!我明明已经写了 if (user && user.profile && user.profile.name) 啊!”user 和 user.profile,但没检查 user.profile.name 本身?哦,其实 user.profile.name 不可能是 undefined 的……等等,如果 user.profile 是空对象呢?”user && user.profile && user.profile.name && user.profile.name.firstName?这代码长得像铁轨,谁看得懂啊!?.。它就像一把瑞士军刀,轻轻一划,所有 undefined 的烦恼都烟消云散。一、传统防守:&& 的“人肉护盾”
const firstName = user && user.profile && user.profile.name && user.profile.name.firstName;null 或 undefined,整个表达式短路返回 undefined,不会报错。但这写法,读起来像在爬楼梯,每层都要确认一下。const result = api && api.getData && api.getData();api.getData 不是函数?又得加判断。二、可选链:
.?. 的优雅空降?. 允许你读取位于连接链深处的属性,而无需显式验证每一环是否有效。如果引用是 null 或 undefined,表达式短路返回 undefined。const firstName = user?.profile?.name?.firstName;user、profile、name 任何一个不存在,整个表达式返回 undefined,而不是报错。2.1 函数调用可选链
const result = api?.getData?.();api 是 null/undefined,或者 api.getData 不是函数,都返回 undefined,不会抛错。2.2 数组元素可选链
const firstItem = arr?.[0];arr 不是数组或者是 null/undefined,返回 undefined。2.3 与空值合并搭配使用
const firstName = user?.profile?.name?.firstName ?? '匿名';undefined 或 null,就换成默认值。完美!三、实战对比:代码简洁度暴增
场景1:读取深层 API 响应
// 旧写法
const city = response && response.data && response.data.user && response.data.user.address && response.data.user.address.city;
// 新写法
const city = response?.data?.user?.address?.city;场景2:调用可选回调
// 旧写法
if (onSuccess && typeof onSuccess === 'function') {
onSuccess(data);
}
// 新写法
onSuccess?.(data);场景3:动态属性名
const value = obj?.[key];四、注意事项:别滥用
?. 只检查左侧是否为 null 或 undefined,不检查 false、0、'' 等假值。如果你需要过滤假值,用 || 或 ??。obj?.prop = value 是语法错误。null/undefined,右侧整个链停止求值,包括函数调用。?. 优化很好,放心用。五、兼容性与降级
@babel/plugin-proposal-optional-chaining 转译。六、总结:告别防御性编程噩梦
&& 来保护每一层属性访问,也不用担心 Cannot read property of undefined 半夜叫醒你。?. 代替 && 链,用 ?? 提供默认值。这两个好基友,能让你的代码年轻十岁。&& 链有多长?评论区晒出你的“防御塔”代码,让大家开开眼!