@@ -20,11 +20,11 @@ alert(user.address.street); // Error!
20
20
或者,在 Web 开发中,我们想获取页面上某个元素的信息,但它可能不存在:
21
21
22
22
``` js run
23
- // querySelector(...) 结果为 null 时报错
23
+ // 如果 querySelector(...) 的结果为 null,则会报错
24
24
let html = document .querySelector (' .my-element' ).innerHTML ;
25
25
```
26
26
27
- 在这门语言( JavaScript)出现 ` ?. ` 前,` && ` 运算符常被用来解决这个问题。
27
+ 在 JavaScript 这门语言中出现 ` ?. ` 前,` && ` 运算符常被用来解决这个问题。
28
28
29
29
例如:
30
30
@@ -34,16 +34,15 @@ let user = {}; // user 没有 address
34
34
alert ( user && user .address && user .address .street ); // undefined(不报错)
35
35
```
36
36
37
- 依次对整条路径上的属性(使用与运算)进行判断 ,以确保所有节点是存在的,但这代码显得累赘 。
37
+ 依次对整条路径上的属性使用与运算进行判断 ,以确保所有节点是存在的,但是写起来很麻烦 。
38
38
39
39
## 可选链
40
40
41
- 如果可选链 ` ?. ` 前一部分是 ` undefined ` 或者 ` null ` ,它会停止运算并返回 ` undefined ` 。
41
+ 如果可选链 ` ?. ` 前面部分是 ` undefined ` 或者 ` null ` ,它会停止运算并返回 ` undefined ` 。
42
42
43
- 为了简明起见,在本文接下来的内容中,我们会说如果一个属性既不是 ` null ` 也不是 ` undefined ` ,那么它就“存在”。
43
+ ** 为了简明起见,在本文接下来的内容中,我们会说如果一个属性既不是 ` null ` 也不是 ` undefined ` ,那么它就“存在”。**
44
44
45
-
46
- 一种安全访问 ` user.address.street ` 的方式:
45
+ 下面这是一种安全地访问 ` user.address.street ` 的方式:
47
46
48
47
``` js run
49
48
let user = {}; // user 没有 address
@@ -57,21 +56,21 @@ alert( user?.address?.street ); // undefined (不报错)
57
56
let user = null ;
58
57
59
58
alert ( user? .address ); // undefined
60
-
61
59
alert ( user? .address .street ); // undefined
62
- alert ( user? .address .street .anything ); // undefined
63
60
` ` `
64
61
65
- 请注意:` ? .` 语法恰好会在它所处的位置起作用,仅此而已,不会对后面起作用。
62
+ 请注意:` ? .` 语法使其前面的值成为可选值,但不会对其后面的起作用。
63
+
64
+ 在上面的例子中,` user? .` 只允许 ` user` 为 ` null / undefined ` 。
66
65
67
- 在最后两行里,运算立即在 ` user? . ` 后面停止,不会继续访问后面的属性。但如果 ` user` 确实存在,那么后面的中间属性,如 ` user .address ` ,就必须存在(才不会报错) 。
66
+ 另一方面,如果 ` user` 存在,那么它必须具有 ` user . address ` 属性,否则 ` user? .address . street ` 在第二个点符号处会报错 。
68
67
69
68
` ` ` warn header= " 不要过度使用可选链"
70
- 我们应该只将 ` ?.` 使用在属性(对象)可以不存在的地方 。
69
+ 我们应该只将 ` ?.` 使用在一些东西可以不存在的地方 。
71
70
72
- 例如,如果根据上面讨论的代码逻辑 ,` user` 对象必须存在,但 ` address` 是可选的,那么 ` user.address?.street` 会更好。
71
+ 例如,如果根据我们的代码逻辑 ,` user` 对象必须存在,但 ` address` 是可选的,那么 ` user.address?.street` 会更好。
73
72
74
- 所以,如果 ` user` 恰巧因为失误变为 undefined ,我们会知道并修复这个失误。相反 ,代码中的 error 在不恰当的地方被消除了,这会导致调试更加困难。
73
+ 所以,如果 ` user` 恰巧因为失误变为 undefined ,我们会知道并修复这个失误。否则 ,代码中的 error 在不恰当的地方被消除了,这会导致调试更加困难。
75
74
` ` `
76
75
77
76
` ` ` ` warn header="` ? .` 前的变量必须已声明"
@@ -81,12 +80,12 @@ alert( user?.address.street.anything ); // undefined
81
80
// ReferenceError: user is not defined
82
81
user? .address ;
83
82
` ` `
84
- 可选链只会去检查 ` null / undefined ` ,不会干扰任何其他语言机制 。
83
+ ` ? . ` 前的变量必须已通过 ` let / const / var user ` 进行声明。可选链仅适用于已声明的变量 。
85
84
` ` ` `
86
85
87
86
## 短路效应
88
87
89
- 正如之前所说 ,如果 ` ? .` 左边部分不存在,它就立即停止运算 (“短路效应”)。
88
+ 正如前面所说的 ,如果 ` ?.` 左边部分不存在,就会立即停止运算 (“短路效应”)。
90
89
91
90
所以,如果后面有任何函数调用或者副作用,它们均不会执行:
92
91
@@ -101,11 +100,11 @@ alert(x); // 0,值没有增加
101
100
102
101
## 其它情况:? .(),? .[]
103
102
104
- 可选链 ` ? .` 不是一个运算符,而是一个特殊的语法结构。它还可以与函数调用和方括号一起使用 。
103
+ 可选链 ` ?.` 不是一个运算符,而是一个特殊的语法结构。它还可以与函数和方括号一起使用 。
105
104
106
- 例如,用 ` ? .()` 来调用一个不存在的函数 。
105
+ 例如,将 ` ?.()` 用于调用一个可能不存在的函数 。
107
106
108
- 在下面代码里,有些用户含有 ` admin` 方法,而有些没有:
107
+ 在下面这段代码中,有些用户具有 ` admin` 方法,而有些没有:
109
108
110
109
` ` ` js run
111
110
let user1 = {
@@ -122,11 +121,11 @@ user2.admin?.();
122
121
*/!*
123
122
` ` `
124
123
125
- 在这两行代码里,我们首先用点 ` .` 来获取 ` admin` 属性,因为用户对象一定存在,直接读取很安全 。
124
+ 在这两行代码中,我们首先使用点符号 ` .` 来获取 ` admin` 属性,因为用户对象一定存在,因此可以安全地读取它 。
126
125
127
- 然后 ` ? .()` 会检查它的左边 :如果 admin 函数存在,那么就调用运行 (对于 ` user1` )。否则(对于 ` user2` )运算停止,没有错误。
126
+ 然后 ` ?.()` 会检查它左边的部分 :如果 admin 函数存在,那么就调用运行它 (对于 ` user1` )。否则(对于 ` user2` )运算停止,没有错误。
128
127
129
- 如果我们想用方括号 ` []` 而不是点 ` .` 来访问属性,语法 ` ? .[]` 也能用 。跟前面的例子类似,它允许从一个可能不存在的对象上安全地读取属性。
128
+ 如果我们想使用方括号 ` []` 而不是点符号 ` .` 来访问属性,语法 ` ?.[]` 也可以使用 。跟前面的例子类似,它允许从一个可能不存在的对象上安全地读取属性。
130
129
131
130
` ` ` js run
132
131
let user1 = {
@@ -149,27 +148,27 @@ alert( user1?.[key]?.something?.not?.existing); // undefined
149
148
delete user?.name; // 如果 user 存在,则删除 user.name
150
149
` ` `
151
150
152
- ` ` ` warn header= " 我们可以使用 `?.` 来安全地读取或者删除 ,但不能写入"
151
+ ` ` ` warn header="我们可以使用 ` ? .` 来安全地读取或删除 ,但不能写入"
153
152
可选链 ` ? .` 不能用在赋值语句的左侧:
154
153
155
154
` ` ` js run
156
- // 下面代码的想法是要写入 user.name,如果 user 存在的话
155
+ // 下面这段代码的想法是要写入 user.name,如果 user 存在的话
157
156
158
- user?.name = "John"; // Error, 不起作用
157
+ user? .name = " John" ; // Error, 不起作用
159
158
// because it evaluates to undefined = "John"
160
159
` ` `
161
160
162
161
## 总结
163
162
164
- ` ?.` 语法有三种形式:
163
+ 可选链 ` ? .` 语法有三种形式:
165
164
166
165
1. ` obj? .prop ` —— 如果 ` obj` 存在则返回 ` obj .prop ` ,否则返回 ` undefined ` 。
167
166
2. ` obj? .[prop]` —— 如果 ` obj` 存在则返回 ` obj[prop]` ,否则返回 ` undefined ` 。
168
167
3. ` obj? .method ()` —— 如果 ` obj` 存在则调用 ` obj .method ()` ,否则返回 ` undefined ` 。
169
168
170
- 如我们所见 ,这些语法形式用起来都很简单直接。` ?.` 检查左边部分是否为 ` null/undefined` ,如果不是则继续运算。
169
+ 正如我们所看到的 ,这些语法形式用起来都很简单直接。` ? .` 检查左边部分是否为 ` null / undefined ` ,如果不是则继续运算。
171
170
172
- ` ?.` 链可以安全地访问嵌套属性 。
171
+ ` ? .` 链使我们能够安全地访问嵌套属性 。
173
172
174
173
但是,我们应该谨慎地使用 ` ? .` ,仅在当左边部分不存在也没问题的情况下使用为宜。
175
174
0 commit comments