可选链的应用

286 阅读2分钟

这是我参与8月更文挑战的第17天,活动详情查看:    8月更文挑战 ​

序言

相信很多朋友都吃过这种bug,因为没有考虑到后端返回不符合规格的数据时,或者数据丢失的情况,导致页面报错,直接挂了,今天我们要讲的可选链? 是一种访问嵌套对象属性的安全的方式,即使中间的属性不存在,也不会报错。

获取不存在属性报错问题

例子1

假设我们有很多个 user 对象,其中存储了我们的用户数据我们大多数用户的家庭成员都存储在 user.kinsfolk 中,兄弟存储在 user.kinsfolk.bother 中,但有些用户没有提供这些信息。 ​

在这种情况下,当我们尝试获取 user.kinsfolk.bother,而该用户恰好没提供兄弟信息,我们则会收到一个错误:

let user = {}; // 一个没有 "kinsfolk" 属性的 user 对象
​
alert(user.kinsfolk.bother ); // Error!

这是预期的结果。JavaScript 的工作原理就是这样的。因为 user.kinsfolk 为 undefined,尝试读取 user.kinsfolk.bother 会失败,并收到一个错误。 但是在很多实际场景中,我们更希望得到的是 undefined(表示没有 bother 属性)而不是一个错误。

例子2

在 Web 开发中,我们可以使用特殊的方法调用(例如document.querySelector('.elem'))以对象的形式获取一个网页元素,如果没有这种对象,则返回 null。

// 如果 document.querySelector('.elem') 的结果为 null,则这里不存在这个元素
let html = document.querySelector('.elem').innerHTML; //ERROR

同样,如果该元素不存在,则访问 null 的 .innerHTML 时会出错。在某些情况下,当元素的缺失是没问题的时候,我们希望避免出现这种错误,而是接受 html = null 作为结果。

解决方案

方案一

可能最先想到的方案是在访问该值的属性之前,使用 if 或条件运算符 ? 对该值进行检查

let user = {};
​
alert(user.kinsfolk ? user.kinsfolk.bother : undefined);
​
alert(user.kinsfolk ? user.kinsfolk.bother ? user.kinsfolk.bother.name : null : null);

这样可以,这里就不会出现错误了。就像你所看到的, user.kinsfolk 在代码中出现了两次。对于嵌套层次更深的属性就会出现更多次这样的重复,尝试获取 user.kinsfolk.bother.name。我们既需要检查 user.kinsfolk,又需要检查 user.kinsfolk.bother。这样代码看起来非常累赘。 ​

方案二

使用可选链,彻底地解决以上所有问题! 如果可选链 ?. 前面的部分是 undefined 或者 null,它会停止运算并返回该部分。 例如 value?.params:

  1. 如果 value 存在,则结果为 value.params,
  2. 否则(当 value 为 undefined/null 时)则返回 undefined。

下面这是一种使用 ?. 安全地访问 user.kinsfolk.bother 的方式:

let user = {}; // user 没有 address 属性
​
alert( user?.kinsfolk?.bother ); // undefined(不报错)

即使 对象 user 不存在,使用 user?kinsfolk来读取地址也不会报错。

let user = null;
​
alert( user?.kinsfolk ); // undefined
alert( user?.kinsfolk.bother ); // undefined