FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [Original HTTPS Page]

docs(object): 链判断运算符移入 Object · lpcman/es6tutorial@f4ce061 · GitHub

Commit f4ce061

Browse files
committed
docs(object): 链判断运算符移入 Object
1 parent 6918f7a commit f4ce061

2 files changed

Lines changed: 133 additions & 133 deletions

File tree

‎docs/object.md‎

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -698,6 +698,139 @@ let runtimeError = {
698698
};
699699
```
700700

701+
## 链判断运算符
702+
703+
编程实务中,如果读取对象内部的某个属性,往往需要判断一下该对象是否存在。比如,要读取`message.body.user.firstName`,安全的写法是写成下面这样。
704+
705+
```javascript
706+
const firstName = (message
707+
&& message.body
708+
&& message.body.user
709+
&& message.body.user.firstName) || 'default';
710+
```
711+
712+
或者使用三元运算符`?:`,判断一个对象是否存在。
713+
714+
```javascript
715+
const fooInput = myForm.querySelector('input[name=foo]')
716+
const fooValue = fooInput ? fooInput.value : undefined
717+
```
718+
719+
这样的层层判断非常麻烦,因此 [ECMAScript2020](https://github.com/tc39/proposal-optional-chaining) 引入了“链判断运算符”(optional chaining operator)`?.`,简化上面的写法。
720+
721+
```javascript
722+
const firstName = message?.body?.user?.firstName || 'default';
723+
const fooValue = myForm.querySelector('input[name=foo]')?.value
724+
```
725+
726+
上面代码使用了`?.`运算符,直接在链式调用的时候判断,左侧的对象是否为`null``undefined`。如果是的,就不再往下运算,而是返回`undefined`
727+
728+
链判断运算符有三种用法。
729+
730+
- `obj?.prop` // 对象属性
731+
- `obj?.[expr]` // 同上
732+
- `func?.(...args)` // 函数或对象方法的调用
733+
734+
下面是判断对象方法是否存在,如果存在就立即执行的例子。
735+
736+
```javascript
737+
iterator.return?.()
738+
```
739+
740+
上面代码中,`iterator.return`如果有定义,就会调用该方法,否则直接返回`undefined`
741+
742+
对于那些可能没有实现的方法,这个运算符尤其有用。
743+
744+
```javascript
745+
if (myForm.checkValidity?.() === false) {
746+
// 表单校验失败
747+
return;
748+
}
749+
```
750+
751+
上面代码中,老式浏览器的表单可能没有`checkValidity`这个方法,这时`?.`运算符就会返回`undefined`,判断语句就变成了`undefined === false`,所以就会跳过下面的代码。
752+
753+
下面是这个运算符常见的使用形式,以及不使用该运算符时的等价形式。
754+
755+
```javascript
756+
a?.b
757+
// 等同于
758+
a == null ? undefined : a.b
759+
760+
a?.[x]
761+
// 等同于
762+
a == null ? undefined : a[x]
763+
764+
a?.b()
765+
// 等同于
766+
a == null ? undefined : a.b()
767+
768+
a?.()
769+
// 等同于
770+
a == null ? undefined : a()
771+
```
772+
773+
上面代码中,特别注意后两种形式,如果`a?.b()`里面的`a.b`不是函数,不可调用,那么`a?.b()`是会报错的。`a?.()`也是如此,如果`a`不是`null``undefined`,但也不是函数,那么`a?.()`会报错。
774+
775+
使用这个运算符,有几个注意点。
776+
777+
(1)短路机制
778+
779+
```javascript
780+
a?.[++x]
781+
// 等同于
782+
a == null ? undefined : a[++x]
783+
```
784+
785+
上面代码中,如果`a``undefined``null`,那么`x`不会进行递增运算。也就是说,链判断运算符一旦为真,右侧的表达式就不再求值。
786+
787+
(2)delete 运算符
788+
789+
```javascript
790+
delete a?.b
791+
// 等同于
792+
a == null ? undefined : delete a.b
793+
```
794+
795+
上面代码中,如果`a``undefined``null`,会直接返回`undefined`,而不会进行`delete`运算。
796+
797+
(3)括号不改变运算顺序
798+
799+
```javascript
800+
(a?.b).c
801+
// 等价于
802+
(a == null ? undefined : a.b).c
803+
```
804+
805+
上面代码中,`?.`对圆括号没有影响,不管`a`对象是否存在,圆括号后面的`.c`总是会执行。
806+
807+
一般来说,使用`?.`运算符的场合,不应该使用圆括号。
808+
809+
(4)报错场合
810+
811+
以下写法是禁止的,会报错。
812+
813+
```javascript
814+
// 构造函数
815+
new a?.()
816+
new a?.b()
817+
818+
// 链判断运算符的右侧有模板字符串
819+
a?.`{b}`
820+
a?.b`{c}`
821+
822+
// 链判断运算符的左侧是 super
823+
super?.()
824+
super?.foo
825+
826+
// 链运算符用于赋值运算符左侧
827+
a?.b = c
828+
```
829+
830+
(5)右侧不得为十进制数值
831+
832+
为了保证兼容以前的代码,允许`foo?.3:0`被解析成`foo ? .3 : 0`,因此规定如果`?.`后面紧跟一个十进制数字,那么`?.`不再被看成是一个完整的运算符,而会按照三元运算符进行处理,也就是说,那个小数点会归属于后面的十进制数字,形成一个小数。
833+
701834
## Null 判断运算符
702835
703836
读取对象属性的时候,如果某个属性的值是`null``undefined`,有时候需要为它们指定默认值。常见做法是通过`||`运算符指定默认值。

‎docs/proposals.md‎

Lines changed: 0 additions & 133 deletions
Original file line numberDiff line numberDiff line change
@@ -118,139 +118,6 @@ class Product {
118118

119119
语法上,`throw`表达式里面的`throw`不再是一个命令,而是一个运算符。为了避免与`throw`命令混淆,规定`throw`出现在行首,一律解释为`throw`语句,而不是`throw`表达式。
120120

121-
## 链判断运算符
122-
123-
编程实务中,如果读取对象内部的某个属性,往往需要判断一下该对象是否存在。比如,要读取`message.body.user.firstName`,安全的写法是写成下面这样。
124-
125-
```javascript
126-
const firstName = (message
127-
&& message.body
128-
&& message.body.user
129-
&& message.body.user.firstName) || 'default';
130-
```
131-
132-
或者使用三元运算符`?:`,判断一个对象是否存在。
133-
134-
```javascript
135-
const fooInput = myForm.querySelector('input[name=foo]')
136-
const fooValue = fooInput ? fooInput.value : undefined
137-
```
138-
139-
这样的层层判断非常麻烦,因此现在有一个[提案](https://github.com/tc39/proposal-optional-chaining),引入了“链判断运算符”(optional chaining operator)`?.`,简化上面的写法。
140-
141-
```javascript
142-
const firstName = message?.body?.user?.firstName || 'default';
143-
const fooValue = myForm.querySelector('input[name=foo]')?.value
144-
```
145-
146-
上面代码使用了`?.`运算符,直接在链式调用的时候判断,左侧的对象是否为`null``undefined`。如果是的,就不再往下运算,而是返回`undefined`
147-
148-
链判断运算符有三种用法。
149-
150-
- `obj?.prop` // 对象属性
151-
- `obj?.[expr]` // 同上
152-
- `func?.(...args)` // 函数或对象方法的调用
153-
154-
下面是判断对象方法是否存在,如果存在就立即执行的例子。
155-
156-
```javascript
157-
iterator.return?.()
158-
```
159-
160-
上面代码中,`iterator.return`如果有定义,就会调用该方法,否则直接返回`undefined`
161-
162-
对于那些可能没有实现的方法,这个运算符尤其有用。
163-
164-
```javascript
165-
if (myForm.checkValidity?.() === false) {
166-
// 表单校验失败
167-
return;
168-
}
169-
```
170-
171-
上面代码中,老式浏览器的表单可能没有`checkValidity`这个方法,这时`?.`运算符就会返回`undefined`,判断语句就变成了`undefined === false`,所以就会跳过下面的代码。
172-
173-
下面是这个运算符常见的使用形式,以及不使用该运算符时的等价形式。
174-
175-
```javascript
176-
a?.b
177-
// 等同于
178-
a == null ? undefined : a.b
179-
180-
a?.[x]
181-
// 等同于
182-
a == null ? undefined : a[x]
183-
184-
a?.b()
185-
// 等同于
186-
a == null ? undefined : a.b()
187-
188-
a?.()
189-
// 等同于
190-
a == null ? undefined : a()
191-
```
192-
193-
上面代码中,特别注意后两种形式,如果`a?.b()`里面的`a.b`不是函数,不可调用,那么`a?.b()`是会报错的。`a?.()`也是如此,如果`a`不是`null``undefined`,但也不是函数,那么`a?.()`会报错。
194-
195-
使用这个运算符,有几个注意点。
196-
197-
(1)短路机制
198-
199-
```javascript
200-
a?.[++x]
201-
// 等同于
202-
a == null ? undefined : a[++x]
203-
```
204-
205-
上面代码中,如果`a``undefined``null`,那么`x`不会进行递增运算。也就是说,链判断运算符一旦为真,右侧的表达式就不再求值。
206-
207-
(2)delete 运算符
208-
209-
```javascript
210-
delete a?.b
211-
// 等同于
212-
a == null ? undefined : delete a.b
213-
```
214-
215-
上面代码中,如果`a``undefined``null`,会直接返回`undefined`,而不会进行`delete`运算。
216-
217-
(3)括号不改变运算顺序
218-
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-
以下写法是禁止的,会报错。
232-
233-
```javascript
234-
// 构造函数
235-
new a?.()
236-
new a?.b()
237-
238-
// 链判断运算符的右侧有模板字符串
239-
a?.`{b}`
240-
a?.b`{c}`
241-
242-
// 链判断运算符的左侧是 super
243-
super?.()
244-
super?.foo
245-
246-
// 链运算符用于赋值运算符左侧
247-
a?.b = c
248-
```
249-
250-
(5)右侧不得为十进制数值
251-
252-
为了保证兼容以前的代码,允许`foo?.3:0`被解析成`foo ? .3 : 0`,因此规定如果`?.`后面紧跟一个十进制数字,那么`?.`不再被看成是一个完整的运算符,而会按照三元运算符进行处理,也就是说,那个小数点会归属于后面的十进制数字,形成一个小数。
253-
254121
## 函数的部分执行
255122

256123
### 语法

0 commit comments

Comments
 (0)

Back | FazBrowse Home | New Git URL