| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -698,6 +698,139 @@ let runtimeError = { | |||
| 698 | 698 | }; | |
| 699 | 699 | ``` | |
| 700 | 700 | ||
| 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 | + | ||
| 701 | 834 | ## Null 判断运算符 | |
| 702 | 835 | ||
| 703 | 836 | 读取对象属性的时候,如果某个属性的值是`null`或`undefined`,有时候需要为它们指定默认值。常见做法是通过`||`运算符指定默认值。 | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -118,139 +118,6 @@ class Product { | |||
| 118 | 118 | ||
| 119 | 119 | 语法上,`throw`表达式里面的`throw`不再是一个命令,而是一个运算符。为了避免与`throw`命令混淆,规定`throw`出现在行首,一律解释为`throw`语句,而不是`throw`表达式。 | |
| 120 | 120 | ||
| 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 | - | ||
| 254 | 121 | ## 函数的部分执行 | |
| 255 | 122 | ||
| 256 | 123 | ### 语法 | |
| Back | FazBrowse Home | New Git URL |
0 commit comments