🔗 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。
