🔗 JavaScript 对象可选链
可选链 ?.
是一种访问嵌套对象属性的安全方式。即便中间的对象不存在,也不会报错。
# 「不存在的属性」
🌰 例子:
let user = {}
// 尝试读取其可能不存在的属性
alert(user.address.street) // Error!
2
3
4
JavaScript 的工作原理就是这样的。因为 user.address
为 undefined
,尝试读取 user.address.street
会失败,并收到一个错误。
但是在很多实际场景中,更希望得到的是 undefined
(表示没有 street
属性)而不是一个错误。
🌰 例子 2:当获取网页中的元素时,
// 如果 document.querySelector('.elem') 的结果为 null,则这里不存在这个元素
let html = document.querySelector('.elem').innerHTML;
// 如果 document.querySelector('.elem') 的结果为 null,则会出现错误
2
3
元素有时候就是获取不到,但是又不想访问时报错。
使用 if
和 ?
三元运算,都给需要编写代码,并且嵌套的代码可读性很差, 不够优雅。可选链 ?.
的出现解决了上面的问题。
# 可选链
语法: value?.prop
:解释为
- 如果
value
存在, 则结果与value.prop
相同。 - 当
value
为undefiend
/null
时,则返回undefined
。
🌰 使用例子:安全访问 user.address.street
:
let user = {}
alert(user?.address?.street)
2
同样可以:
let user = null
alert(user?.address)
alert(user?.address.street)
2
3
?.
可选链使前面的值成为可选值,但不会对后面起作用。在
user?.address.street.name
中,?.
允许user
为null/undefined
(在这种情况下会返回undefined
)也不会报错,但这仅对于user
。更深层次的属性是通过常规方式访问的。如果希望它们中的一些属性也是可选的,那么需要使用更多的?.
来替换.
。
🌰 使用例子:获取网页中的元素:
let html = document.querySelector('.elem')?.innerHTML
// 如果没有符合的元素则为undefiend
2
注意
不能过度使用可选链:应该只将 ?.
使用在一些东西可以不存在的地方。
例如,如果根据代码逻辑, user
对象必须存在,但 address
是可选的,那么我们应该这样写 user.address?.street
,而不是这样 user?.address?.street
。
注意
可选链仅适用于已声明的变量。 ?.
前面的变量必须要为已声明。(例如 let/const/var user
或作为一个函数参数)
🌰 例子:当 user
未声明:
user?.address // user is not defined
# 短路效应
只要 ?.
左边的部分不存在,则其后的一系列函数调用或者操作都不会执行。
🌰 例子:
let user = null
let x = 0
user?.sayHi(x++)
alert(x)
2
3
4
5
由于 user
不存在,所以其后的 sayHi
不会执行,所以 x
值不发生变化。
# 可选链的其他变体 ?.()
, ?.[]
可选链 ?.
不是一个运算符,而是一个特殊的语法结构。它还可以与函数和方括号一起使用。
🌰 例子: ?.()
用于调用一个可能不存在的函数。
let userAdmin = {
admin() {
alert('i am admin')
}
}
let userGuest = {}
userAdmin.admin?.()
userGuest.admin?.()
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
2
3
4
5
6
7
8
9
10
🌰 配合 delete
一起使用:
delete user?.name // 当user存在才删除user.name
可选链仅仅用做安全读取或者删除,但是不能写入。(不能放在赋值语句的左边 )
🌰 例子:
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
。