@@ -20,11 +20,11 @@ alert(user.address.street); // Error!
2020或者,在 Web 开发中,我们想获取页面上某个元素的信息,但它可能不存在:
2121
2222``` js run
23- // querySelector(...) 结果为 null 时报错
23+ // 如果 querySelector(...) 的结果为 null,则会报错
2424let html = document .querySelector (' .my-element' ).innerHTML ;
2525```
2626
27- 在这门语言( JavaScript)出现 ` ?. ` 前,` && ` 运算符常被用来解决这个问题。
27+ 在 JavaScript 这门语言中出现 ` ?. ` 前,` && ` 运算符常被用来解决这个问题。
2828
2929例如:
3030
@@ -34,16 +34,15 @@ let user = {}; // user 没有 address
3434alert ( user && user .address && user .address .street ); // undefined(不报错)
3535```
3636
37- 依次对整条路径上的属性(使用与运算)进行判断 ,以确保所有节点是存在的,但这代码显得累赘 。
37+ 依次对整条路径上的属性使用与运算进行判断 ,以确保所有节点是存在的,但是写起来很麻烦 。
3838
3939## 可选链
4040
41- 如果可选链 ` ?. ` 前一部分是 ` undefined ` 或者 ` null ` ,它会停止运算并返回 ` undefined ` 。
41+ 如果可选链 ` ?. ` 前面部分是 ` undefined ` 或者 ` null ` ,它会停止运算并返回 ` undefined ` 。
4242
43- 为了简明起见,在本文接下来的内容中,我们会说如果一个属性既不是 ` null ` 也不是 ` undefined ` ,那么它就“存在”。
43+ ** 为了简明起见,在本文接下来的内容中,我们会说如果一个属性既不是 ` null ` 也不是 ` undefined ` ,那么它就“存在”。**
4444
45-
46- 一种安全访问 ` user.address.street ` 的方式:
45+ 下面这是一种安全地访问 ` user.address.street ` 的方式:
4746
4847``` js run
4948let user = {}; // user 没有 address
@@ -57,21 +56,21 @@ alert( user?.address?.street ); // undefined (不报错)
5756let user = null ;
5857
5958alert ( user? .address ); // undefined
60-
6159alert ( user? .address .street ); // undefined
62- alert ( user? .address .street .anything ); // undefined
6360` ` `
6461
65- 请注意:` ? .` 语法恰好会在它所处的位置起作用,仅此而已,不会对后面起作用。
62+ 请注意:` ? .` 语法使其前面的值成为可选值,但不会对其后面的起作用。
63+
64+ 在上面的例子中,` user? .` 只允许 ` user` 为 ` null / undefined ` 。
6665
67- 在最后两行里,运算立即在 ` user? . ` 后面停止,不会继续访问后面的属性。但如果 ` user` 确实存在,那么后面的中间属性,如 ` user .address ` ,就必须存在(才不会报错) 。
66+ 另一方面,如果 ` user` 存在,那么它必须具有 ` user . address ` 属性,否则 ` user? .address . street ` 在第二个点符号处会报错 。
6867
6968` ` ` warn header= " 不要过度使用可选链"
70- 我们应该只将 ` ?.` 使用在属性(对象)可以不存在的地方 。
69+ 我们应该只将 ` ?.` 使用在一些东西可以不存在的地方 。
7170
72- 例如,如果根据上面讨论的代码逻辑 ,` user` 对象必须存在,但 ` address` 是可选的,那么 ` user.address?.street` 会更好。
71+ 例如,如果根据我们的代码逻辑 ,` user` 对象必须存在,但 ` address` 是可选的,那么 ` user.address?.street` 会更好。
7372
74- 所以,如果 ` user` 恰巧因为失误变为 undefined ,我们会知道并修复这个失误。相反 ,代码中的 error 在不恰当的地方被消除了,这会导致调试更加困难。
73+ 所以,如果 ` user` 恰巧因为失误变为 undefined ,我们会知道并修复这个失误。否则 ,代码中的 error 在不恰当的地方被消除了,这会导致调试更加困难。
7574` ` `
7675
7776` ` ` ` warn header="` ? .` 前的变量必须已声明"
@@ -81,12 +80,12 @@ alert( user?.address.street.anything ); // undefined
8180// ReferenceError: user is not defined
8281user? .address ;
8382` ` `
84- 可选链只会去检查 ` null / undefined ` ,不会干扰任何其他语言机制 。
83+ ` ? . ` 前的变量必须已通过 ` let / const / var user ` 进行声明。可选链仅适用于已声明的变量 。
8584` ` ` `
8685
8786## 短路效应
8887
89- 正如之前所说 ,如果 ` ? .` 左边部分不存在,它就立即停止运算 (“短路效应”)。
88+ 正如前面所说的 ,如果 ` ?.` 左边部分不存在,就会立即停止运算 (“短路效应”)。
9089
9190所以,如果后面有任何函数调用或者副作用,它们均不会执行:
9291
@@ -101,11 +100,11 @@ alert(x); // 0,值没有增加
101100
102101## 其它情况:? .(),? .[]
103102
104- 可选链 ` ? .` 不是一个运算符,而是一个特殊的语法结构。它还可以与函数调用和方括号一起使用 。
103+ 可选链 ` ?.` 不是一个运算符,而是一个特殊的语法结构。它还可以与函数和方括号一起使用 。
105104
106- 例如,用 ` ? .()` 来调用一个不存在的函数 。
105+ 例如,将 ` ?.()` 用于调用一个可能不存在的函数 。
107106
108- 在下面代码里,有些用户含有 ` admin` 方法,而有些没有:
107+ 在下面这段代码中,有些用户具有 ` admin` 方法,而有些没有:
109108
110109` ` ` js run
111110let user1 = {
@@ -122,11 +121,11 @@ user2.admin?.();
122121*/!*
123122` ` `
124123
125- 在这两行代码里,我们首先用点 ` .` 来获取 ` admin` 属性,因为用户对象一定存在,直接读取很安全 。
124+ 在这两行代码中,我们首先使用点符号 ` .` 来获取 ` admin` 属性,因为用户对象一定存在,因此可以安全地读取它 。
126125
127- 然后 ` ? .()` 会检查它的左边 :如果 admin 函数存在,那么就调用运行 (对于 ` user1` )。否则(对于 ` user2` )运算停止,没有错误。
126+ 然后 ` ?.()` 会检查它左边的部分 :如果 admin 函数存在,那么就调用运行它 (对于 ` user1` )。否则(对于 ` user2` )运算停止,没有错误。
128127
129- 如果我们想用方括号 ` []` 而不是点 ` .` 来访问属性,语法 ` ? .[]` 也能用 。跟前面的例子类似,它允许从一个可能不存在的对象上安全地读取属性。
128+ 如果我们想使用方括号 ` []` 而不是点符号 ` .` 来访问属性,语法 ` ?.[]` 也可以使用 。跟前面的例子类似,它允许从一个可能不存在的对象上安全地读取属性。
130129
131130` ` ` js run
132131let user1 = {
@@ -149,27 +148,27 @@ alert( user1?.[key]?.something?.not?.existing); // undefined
149148delete user?.name; // 如果 user 存在,则删除 user.name
150149` ` `
151150
152- ` ` ` warn header= " 我们可以使用 `?.` 来安全地读取或者删除 ,但不能写入"
151+ ` ` ` warn header="我们可以使用 ` ? .` 来安全地读取或删除 ,但不能写入"
153152可选链 ` ? .` 不能用在赋值语句的左侧:
154153
155154` ` ` js run
156- // 下面代码的想法是要写入 user.name,如果 user 存在的话
155+ // 下面这段代码的想法是要写入 user.name,如果 user 存在的话
157156
158- user?.name = "John"; // Error, 不起作用
157+ user? .name = " John" ; // Error, 不起作用
159158// because it evaluates to undefined = "John"
160159` ` `
161160
162161## 总结
163162
164- ` ?.` 语法有三种形式:
163+ 可选链 ` ? .` 语法有三种形式:
165164
1661651. ` obj? .prop ` —— 如果 ` obj` 存在则返回 ` obj .prop ` ,否则返回 ` undefined ` 。
1671662. ` obj? .[prop]` —— 如果 ` obj` 存在则返回 ` obj[prop]` ,否则返回 ` undefined ` 。
1681673. ` obj? .method ()` —— 如果 ` obj` 存在则调用 ` obj .method ()` ,否则返回 ` undefined ` 。
169168
170- 如我们所见 ,这些语法形式用起来都很简单直接。` ?.` 检查左边部分是否为 ` null/undefined` ,如果不是则继续运算。
169+ 正如我们所看到的 ,这些语法形式用起来都很简单直接。` ? .` 检查左边部分是否为 ` null / undefined ` ,如果不是则继续运算。
171170
172- ` ?.` 链可以安全地访问嵌套属性 。
171+ ` ? .` 链使我们能够安全地访问嵌套属性 。
173172
174173但是,我们应该谨慎地使用 ` ? .` ,仅在当左边部分不存在也没问题的情况下使用为宜。
175174
0 commit comments