Skip to content

Commit 2f1c271

Browse files
committed
docs(proposal): edit optional chaining
1 parent f828a2c commit 2f1c271

File tree

1 file changed

+48
-13
lines changed

1 file changed

+48
-13
lines changed

docs/proposals.md

Lines changed: 48 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -129,29 +129,48 @@ const firstName = (message
129129
&& message.body.user.firstName) || 'default';
130130
```
131131

132+
或者使用三元运算符`?:`,判断一个对象是否存在。
133+
134+
```javascript
135+
const fooInput = myForm.querySelector('input[name=foo]')
136+
const fooValue = fooInput ? fooInput.value : undefined
137+
```
138+
132139
这样的层层判断非常麻烦,因此现在有一个[提案](https://github.com/tc39/proposal-optional-chaining),引入了“链判断运算符”(optional chaining operator)`?.`,简化上面的写法。
133140

134141
```javascript
135142
const firstName = message?.body?.user?.firstName || 'default';
143+
const fooValue = myForm.querySelector('input[name=foo]')?.value
136144
```
137145
138-
上面代码有三个`?.`运算符,直接在链式调用的时候判断,左侧的对象是否为`null``undefined`。如果是的,就不再往下运算,而是返回`undefined`
146+
上面代码使用了`?.`运算符,直接在链式调用的时候判断,左侧的对象是否为`null``undefined`。如果是的,就不再往下运算,而是返回`undefined`
139147
140-
链判断运算符号有三种用法
148+
链判断运算符有三种用法
141149
142-
- `obj?.prop` // 读取对象属性
150+
- `obj?.prop` // 对象属性
143151
- `obj?.[expr]` // 同上
144152
- `func?.(...args)` // 函数或对象方法的调用
145153
146-
下面是判断函数是否存在的例子
154+
下面是判断对象方法是否存在,如果存在就立即执行的例子
147155
148156
```javascript
149157
iterator.return?.()
150158
```
151159
152160
上面代码中,`iterator.return`如果有定义,就会调用该方法,否则直接返回`undefined`
153161
154-
下面是更多的例子。
162+
对于那些可能没有实现的方法,这个运算符尤其有用。
163+
164+
```javascript
165+
if (myForm.checkValidity?.() === false) {
166+
// 表单校验失败
167+
return;
168+
}
169+
```
170+
171+
上面代码中,老式浏览器的表单可能没有`checkValidity`这个方法,这时`?.`运算符就会返回`undefined`,判断语句就变成了`undefined === false`,所以就会跳过下面的代码。
172+
173+
下面是这个运算符常见的使用形式,以及不使用该运算符时的等价形式。
155174
156175
```javascript
157176
a?.b
@@ -171,6 +190,8 @@ a?.()
171190
a == null ? undefined : a()
172191
```
173192
193+
上面代码中,特别注意后两种形式,如果`a?.b()`里面的`a.b`不是函数,不可调用,那么`a?.b()`是会报错的。`a?.()`也是如此,如果`a`不是`null``undefined`,但也不是函数,那么`a?.()`会报错。
194+
174195
使用这个运算符,有几个注意点。
175196
176197
(1)短路机制
@@ -193,26 +214,40 @@ a == null ? undefined : delete a.b
193214
194215
上面代码中,如果`a``undefined``null`,会直接返回`undefined`,而不会进行`delete`运算。
195216
196-
(3)报错场合
217+
(3)括号不改变运算顺序
197218
198-
以下写法是禁止,会报错。
219+
```javascript
220+
(a?.b).c
221+
// 等价于
222+
(a == null ? undefined : a.b).c
223+
```
224+
225+
上面代码中,`?.`对圆括号没有影响,不管`a`对象是否存在,圆括号后面的`.c`总是会执行。
226+
227+
一般来说,使用`?.`运算符的场合,不应该使用圆括号。
228+
229+
(4)报错场合
230+
231+
以下写法是禁止的,会报错。
199232
200233
```javascript
201-
// 构造函数判断
234+
// 构造函数
202235
new a?.()
236+
new a?.b()
203237

204-
// 运算符右侧是模板字符串
238+
// 链判断运算符的右侧有模板字符串
205239
a?.`{b}`
206-
207-
// 链判断运算符前后有构造函数或模板字符串
208-
new a?.b()
209240
a?.b`{c}`
210241

242+
// 链判断运算符的左侧是 super
243+
super?.()
244+
super?.foo
245+
211246
// 链运算符用于赋值运算符左侧
212247
a?.b = c
213248
```
214249
215-
4)右侧不得为十进制数值
250+
5)右侧不得为十进制数值
216251
217252
为了保证兼容以前的代码,允许`foo?.3:0`被解析成`foo ? .3 : 0`,因此规定如果`?.`后面紧跟一个十进制数字,那么`?.`不再被看成是一个完整的运算符,而会按照三元运算符进行处理,也就是说,那个小数点会归属于后面的十进制数字,形成一个小数。
218253

0 commit comments

Comments
 (0)