目录

🔗 JavaScript 对象可选链

可选链 ?. 是一种访问嵌套对象属性的安全方式。即便中间的对象不存在,也不会报错。

# 「不存在的属性」

🌰 例子:

let user = {}

// 尝试读取其可能不存在的属性
alert(user.address.street) // Error!
1
2
3
4

JavaScript 的工作原理就是这样的。因为 user.addressundefined ,尝试读取 user.address.street 会失败,并收到一个错误。

但是在很多实际场景中,更希望得到的是 undefined (表示没有 street 属性)而不是一个错误。

🌰 例子 2:当获取网页中的元素时,

// 如果 document.querySelector('.elem') 的结果为 null,则这里不存在这个元素
let html = document.querySelector('.elem').innerHTML; 
// 如果 document.querySelector('.elem') 的结果为 null,则会出现错误
1
2
3

元素有时候就是获取不到,但是又不想访问时报错。

使用 if? 三元运算,都给需要编写代码,并且嵌套的代码可读性很差, 不够优雅。可选链 ?. 的出现解决了上面的问题。

# 可选链

语法: value?.prop :解释为

  • 如果 value 存在, 则结果与 value.prop 相同。
  • valueundefiend / null 时,则返回 undefined

🌰 使用例子:安全访问 user.address.street

let user = {}
alert(user?.address?.street)
1
2

同样可以:

let user = null
alert(user?.address)
alert(user?.address.street)
1
2
3

?. 可选链使前面的值成为可选值,但不会对后面起作用。

user?.address.street.name 中, ?. 允许 usernull/undefined (在这种情况下会返回 undefined )也不会报错,但这仅对于 user 。更深层次的属性是通过常规方式访问的。如果希望它们中的一些属性也是可选的,那么需要使用更多的 ?. 来替换 .

🌰 使用例子:获取网页中的元素:

let html = document.querySelector('.elem')?.innerHTML
// 如果没有符合的元素则为undefiend
1
2

注意

不能过度使用可选链:应该只将 ?. 使用在一些东西可以不存在的地方。

例如,如果根据代码逻辑, user 对象必须存在,但 address 是可选的,那么我们应该这样写 user.address?.street ,而不是这样 user?.address?.street

注意

可选链仅适用于已声明的变量。 ?. 前面的变量必须要为已声明。(例如 let/const/var user 或作为一个函数参数)

🌰 例子:当 user 未声明:

user?.address // user is not defined
1

# 短路效应

只要 ?. 左边的部分不存在,则其后的一系列函数调用或者操作都不会执行。

🌰 例子:

let user = null
let x = 0

user?.sayHi(x++)
alert(x)
1
2
3
4
5

由于 user 不存在,所以其后的 sayHi 不会执行,所以 x 值不发生变化。

# 可选链的其他变体 ?.() , ?.[]

可选链 ?. 不是一个运算符,而是一个特殊的语法结构。它还可以与函数和方括号一起使用

🌰 例子: ?.() 用于调用一个可能不存在的函数。

let userAdmin = {
  admin() {
    alert('i am admin') 
  }
}

let userGuest = {}
userAdmin.admin?.()
userGuest.admin?.()
1
2
3
4
5
6
7
8
9

首先使用点符号( userAdmin.admin )来获取 admin 属性,假定对象 userAdmin 存在,因此可以安全地读取它。

admin 是否存在,存在才调用。如果不存在,则无法调用,并且不报错。

🌰 例子: ?.[] 访问一个可能不存在的属性:

let key = "firstName";

let user1 = {
  firstName: "John"
};

let user2 = null;

alert( user1?.[key] ); // John
alert( user2?.[key] ); // undefined
1
2
3
4
5
6
7
8
9
10

🌰 配合 delete 一起使用:

delete user?.name // 当user存在才删除user.name
1

可选链仅仅用做安全读取或者删除,但是不能写入。(不能放在赋值语句的左边 )

🌰 例子:

let user = null
user?.name = 'Simon' // 可以看作 undefined = 'Simon'
1
2

# 可选链总结

  • 可选链有三种形式(分别对应读取属性和读取方法):
    • obj?.prop 如果 obj 存在则返回 obj.prop ,否则返回 undefined
    • obj?.[prop] 如果 obj 存在则返回 obj[prop] ,否则返回 undefined
    • obj.method 如果 obj.method 存在则调用 obj.method() ,否则返回 undefined
📢 上次更新: 2022/09/02, 10:18:16