可选链 “?.
”
可选链 ?.
是一种访问嵌套对象属性的安全的方式。即使中间的属性不存在,也不会出现错误。
类似于.
链式访问,但是链式访问在中间某个属性不存在时,会报错。
语法和解析
obj?.prop // 如果 obj 存在则返回 obj.prop,否则返回 undefined。
// 等同于
obj == null || obj == undefined ? undefined : obj.prop
obj?.[prop] // 如果 obj 存在则返回 obj[prop],否则返回 undefined。
// 等同于
obj == null || obj == undefined ? undefined : obj[prop]
obj?.method() // 验证obj存在则执行method(),否则返回undefined
// 等同于
obj == null || obj == undefined ? undefined : obj.method()
obj.method?.() // 如果 obj.method 存在则调用 obj.method(),否则返回 undefined。
// 等同于:obj对象必须存在,method()可选
typeof obj.method == "function" ? obj.method() ? undefined
访问“不存在属性”
如果某个属性不存在:
let user = null
let name = user.name // 报错 Uncaught TypeError: Cannot read properties of null (reading 'name')
因为 user
为 null
,尝试读取 user.name
会失败,并收到一个错误。
但是在实际应用场景中,我们可能希望返回的值是undefined
。
为了避免报错,我们需要明确校验user
:
let user = null
let name1 = user ? user.name : undefined // undefined
let name2 = user && user.name; // undefined
使用可选链?.
,不需要明确校验user
:
let user = null
let name = user?.name // undefined
let street = user?.address?.street // undefined
使用可选链?.
,JavaScript 会在尝试访问 user.name
之前,先隐式地检查并确定 user
是否存在(user
是不是null/undefined
)。
解析user?.name
:
user
存在(既不是null
,也不是undefined
),则结果与user.name
相同,user
不存在(当user
为undefined/null
时),则返回undefined
。
请注意:?.
语法使其前面的值成为可选值,但不会对其后面的起作用。
例如,在 user?.address.street
中,?.
允许 user
为 null/undefined
(在这种情况下会返回 undefined
)也不会报错,但这仅对于 user
。
user
后面的属性是通过常规方式.
访问的。如果address
属性为 null/undefined
,会立即报错。
如果希望不报错,那要让每个属性都是可选的,即使用 ?.
来替换 .
:user?.address?.street
,?.
允许user
,address
,street
为 null/undefined
。
可选链?.[]
访问属性
let user = {
name: "zhang",
"like music": true
}
alert( user?.name); // zhang
alert( user?.["like music"] ) // true
可选链?.()
访问对象的方法
let user = {
sayBaiBai: "baibai",
sayHi() {
alert("hello")
}
}
user.sayHi?.(); // hello
user.sayYes?.(); // undefined, 啥都没发生(没有这样的方法)
user.sayBaibai?.(); // undefined, 啥都没发生(没有这样的方法)
可选链?.
访问数组
let arr = [1, 3, 5]
alert( arr?.[0] ); // 1
可选链 ?.
前的变量必须已声明
// ReferenceError: user is not defined
user?.name; // 报错,未声明变量 user
可选链 ?.
不能用于赋值
let user = null
user?.name = "Zhang" // Error,不起作用
// 因为它在计算的是:undefined = "Zhang"
let admin = {}
admin?.name = "zhang" // Error
// Uncaught SyntaxError: Invalid left-hand side in assignment
?.
导致短路效应
当在表达式中使用可选链时,如果 ?.
左边部分是 null
或 undefined
,就会立即停止运算(“短路效应”)。
因此,如果在 ?.
的右侧有任何进一步的函数调用或操作,它们均不会执行。
let user = null;
let x = 0;
// 读取user.key1
user?.[key`${x++}`]; // 没有 "user",因此代码执行没有到达 sayHi 调用和 x++
alert(x); // 0,值没有增加
连续使用可选链
let user = {
name: "zhang",
details: {
likes: {
music: true
}
}
}
let isLikeMusic = user?.details?.likes?.music // true
let english = user?.details?.likes?.english // undefined
总结
可选链?.
检查左边部分是否为 null/undefined
,如果不是则继续运算,否则立即停止运算。
可选链 ?.
前的变量必须已声明。
可选链 ?.
不能用于赋值。
可选链?.
链使我们能够安全地访问嵌套属性。
根据代码逻辑,仅在当左侧部分不存在也可接受的情况下,谨慎地使用 ?.
。滥用 ?.
,会导致代码中的错误在不应该被消除的地方消除了,增加调试难度。