一、可选链?.语法有三种形式:
1、obj?.prop—— 如果obj存在则返回obj.prop,否则返回undefined。
2、obj?.[prop]—— 如果obj存在则返回obj[prop],否则返回undefined。
3、obj.method?.()—— 如果obj.method存在则调用obj.method(),否则返回undefined。
二、如果可选链?.前面的部分是undefined或者null,它会停止运算并返回该部分。
三、如果一个属性既不是null也不是undefined,那么它就“存在”。
1、换句话说,例如value?.prop:
- 如果value存在,则结果与value.prop相同,
- 否则(当value为undefined/null时)则返回undefined。 | 【示例】使用?.安全地访问user.address.street的方式:```javascript let user = {}; // user 没有 address 属性
alert( user?.address?.street ); // undefined(不报错)
即使 对象user不存在,使用user?.address来读取地址也没问题:```javascript
let user = null;
alert( user?.address ); // undefined
alert( user?.address.street ); // undefined
| | —- |
五、?.语法使其前面的值成为可选值,但不会对其后面的起作用。
【示例】在user?.address.street.name中,?.允许user为null/undefined,但仅此而已。更深层次的属性是通过常规方式访问的。如果我们希望它们中的一些也是可选的,那么我们需要使用更多的?.来替换.。 |
---|
六、不要过度使用可选链
1、我们应该只将?.使用在一些东西可以不存在的地方。
【示例】如果根据我们的代码逻辑,user对象必须存在,但address是可选的,那么我们应该这样写user.address?.street,而不是这样user?.address?.street。 所以,如果user恰巧因为失误变为 undefined,我们会看到一个编程错误并修复它。否则,代码中的错误在不恰当的地方被消除了,这会导致调试更加困难。 |
---|
七、?.前的变量必须已声明,可选链仅适用于已声明的变量。
| 【示例】如果未声明变量user,那么user?.anything会触发一个错误:```javascript // ReferenceError: user is not defined user?.address;
|
| --- |
<a name="UAT4k"></a>
# 短路效应
一、如果?.左边部分不存在,就会立即停止运算(“短路效应”)。<br />二、如果后面有任何函数调用或者副作用,它们均不会执行。
| 【示例】```javascript
let user = null;
let x = 0;
user?.sayHi(x++); // 没有 "sayHi",因此代码执行没有触达 x++
alert(x); // 0,值没有增加
| | —- |
其它变体:?.(),?.[]
一、可选链?.不是一个运算符,而是一个特殊的语法结构。它还可以与函数和方括号一起使用。
二、将?.()用于调用一个可能不存在的函数。
| 【示例】有些用户具有admin方法,而有些没有:```javascript let userAdmin = { admin() { alert(“I am admin”); } };
let userGuest = {};
userAdmin.admin?.(); // I am admin
userGuest.admin?.(); // 啥都没有(没有这样的方法)
1、在这两行代码中,我们首先使用点符号(user1.admin)来获取admin属性,因为用户对象一定存在,因此可以安全地读取它。<br />2、然后?.()会检查它左边的部分:如果admin函数存在,那么就调用运行它(对于user1)。否则(对于user2)运算停止,没有错误。 |
| --- |
三、如果我们想使用方括号[]而不是点符号.来访问属性,语法?.[]也可以使用。<br />1、它允许从一个可能不存在的对象上安全地读取属性。
| 【示例】```javascript
let user1 = {
firstName: "John"
};
let user2 = null; // 假设,我们不能授权此用户
let key = "firstName";
alert( user1?.[key] ); // John
alert( user2?.[key] ); // undefined
alert( user1?.[key]?.something?.not?.existing); // undefined
| | —- |
四、我们还可以将?.跟delete一起使用:
| 【示例】```javascript delete user?.name; // 如果 user 存在,则删除 user.name
|
| --- |
五、我们可以使用?.来安全地读取或删除,但不能写入<br />1、可选链?.不能用在赋值语句的左侧。
| 【示例】```javascript
let user = null;
user?.name = "John"; // Error,不起作用
// 因为它在计算的是 undefined = "John"
| | —- |
规范
es2020