1
- # 多变量的模式赋值
1
+ # 变量的解构赋值
2
2
3
- ES6允许按照一定模式,一次性对多个变量进行赋值,这又称为解构(Destructuring)。
3
+ ## 数组的解构赋值
4
4
5
- 正常情况下,为多个变量赋值,只能一次次分开赋值。
5
+ ES6允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构(Destructuring)。
6
+
7
+ 以前,为变量赋值,只能直接指定值。
6
8
7
9
``` javascript
8
10
@@ -20,89 +22,207 @@ var [a, b, c] = [1, 2, 3];
20
22
21
23
```
22
24
23
- 本质上,这种写法属于模式匹配,只要等号两边的模式相同,左边的变量就会被赋予对应的值。下面是一些嵌套数组进行模式赋值的例子。
25
+ 上面代码表示,可以从数组中提取值,按照对应位置,对变量赋值。
26
+
27
+ 本质上,这种写法属于“模式匹配”,只要等号两边的模式相同,左边的变量就会被赋予对应的值。下面是一些使用嵌套数组进行解构的例子。
24
28
25
29
``` javascript
26
30
27
- var [foo, [[bar], baz]] = [1 , [[2 ], 3 ]]
31
+ var [foo, [[bar], baz]] = [1 , [[2 ], 3 ]];
32
+ foo // 1
33
+ bar // 2
34
+ baz // 3
28
35
29
- var [,,third] = [" foo" , " bar" , " baz" ]
36
+ var [,,third] = [" foo" , " bar" , " baz" ];
37
+ third // "baz"
30
38
31
- var [head, ... tail] = [1 , 2 , 3 , 4 ]
39
+ var [head, ... tail] = [1 , 2 , 3 , 4 ];
40
+ head // 1
41
+ tail // [2, 3, 4]
32
42
33
43
```
34
44
35
- 模式赋值还允许指定默认值 。
45
+ 如果解构不成功,变量的值就等于undefined 。
36
46
37
47
``` javascript
38
48
39
- var [missing = true ] = [];
49
+ var [foo] = [];
50
+ var [foo] = 1 ;
51
+ var [foo] = ' Hello' ;
52
+ var [foo] = false ;
53
+ var [foo] = NaN ;
40
54
41
- console .log (missing)
42
- // true
55
+ ```
43
56
44
- var { x = 3 } = {};
45
- console .log (x)
46
- // 3
57
+ 以上几种情况都属于解构不成功,foo的值都会等于undefined。但是,如果对undefined或null进行解构,就会报错。
58
+
59
+ ``` javascript
60
+
61
+ // 报错
62
+ var [foo] = undefined ;
63
+ var [foo] = null ;
64
+
65
+ ```
66
+
67
+ 这是因为解构只能用于数组或对象。其他原始类型的值都可以转为相应的对象,但是,undefined和null不能转为对象,因此报错。
68
+
69
+ 解构赋值允许指定默认值。
70
+
71
+ ``` javascript
72
+
73
+ var [foo = true ] = [];
74
+ foo // true
75
+
76
+ ```
77
+
78
+ 解构赋值不仅适用于var命令,也适用于let和const命令。
79
+
80
+ ``` javascript
81
+
82
+ var [v1, v2, ... , vN ] = array;
83
+ let [v1, v2, ... , vN ] = array;
84
+ const [v1 , v2 , ... , vN ] = array;
85
+
86
+ ```
87
+
88
+ ## 对象的解构赋值
89
+
90
+ 解构不仅可以用于数组,还可以用于对象。
91
+
92
+ ``` javascript
93
+
94
+ var { foo, bar } = { foo: " aaa" , bar: " bbb" };
95
+ foo // "aaa"
96
+ bar // "bbb"
47
97
48
98
```
49
99
50
- 模式赋值不仅可以用于数组,还可以用于对象 。
100
+ 对象的解构与数组有一个重要的不同。数组的元素是按次序排列的,变量的取值由它的位置决定;而对象的属性没有次序,变量必须与属性同名,才能取到正确的值 。
51
101
52
102
``` javascript
53
103
54
- var { foo, bar } = { foo: " lorem" , bar: " ipsum" };
104
+ var { bar, foo } = { foo: " aaa" , bar: " bbb" };
105
+ foo // "aaa"
106
+ bar // "bbb"
55
107
56
- foo // "lorem"
57
- bar // "ipsum"
108
+ var { baz } = { foo: " aaa" , bar: " bbb" };
109
+ baz // undefined
110
+
111
+ ```
112
+
113
+ 上面代码的第一个例子,等号左边的两个变量的次序,与等号右边两个同名属性的次序不一致,但是对取值完全没有影响。第二个例子的变量没有对应的同名属性,导致取不到值,最后等于` undefined ` 。
114
+
115
+ 如果变量名与属性名不一致,必须写成下面这样。
116
+
117
+ ``` javascript
118
+
119
+ var { foo: baz } = { foo: " aaa" , bar: " bbb" };
120
+ baz // "aaa"
121
+
122
+ ```
123
+
124
+ 和数组一样,解构也可以用于嵌套结构的对象。
125
+
126
+ ``` javascript
58
127
59
128
var o = {
60
- p1 : [
129
+ p : [
61
130
" Hello" ,
62
- { p2 : " World" }
131
+ { y : " World" }
63
132
]
64
133
};
65
134
66
- var { a: [x, { y }] } = o;
67
-
135
+ var { p: [x, { y }] } = o;
68
136
x // "Hello"
69
137
y // "World"
70
138
71
139
```
72
140
73
- 这种写法的用途很多。
141
+ 对象的解构也可以指定默认值。
142
+
143
+ ``` javascript
144
+
145
+ var { x = 3 } = {};
146
+ x // 3
147
+
148
+ ```
74
149
75
- (1)交换变量的值
150
+ 如果要将一个已经声明的变量用于解构赋值,必须非常小心。
151
+
152
+ ``` javascript
153
+
154
+ // 错误的写法
155
+
156
+ var x;
157
+ {x} = {x: 1 };
158
+ // SyntaxError: syntax error
159
+
160
+ ```
161
+
162
+ 上面代码的写法会报错,因为JavaScript引擎会将` {x} ` 理解成一个代码块,从而发生语法错误。只有不将大括号写在行首,才能避免这个问题。
163
+
164
+ ``` javascript
165
+
166
+ // 正确的写法
167
+
168
+ ({x}) = {x: 1 };
169
+ // 或者
170
+ ({x} = {x: 1 });
171
+
172
+ ```
173
+
174
+ ## 用途
175
+
176
+ 变量的解构赋值用途很多。
177
+
178
+ ** (1)交换变量的值**
76
179
77
180
``` javascript
78
181
79
182
[x, y] = [y, x];
80
183
81
184
```
82
185
83
- (2)从函数返回多个值
186
+ ** (2)从函数返回多个值**
187
+
188
+ 函数只能返回一个值,如果要返回多个值,只能将它们放在数组或对象里返回。有了解构赋值,取出这些值就非常方便。
84
189
85
190
``` javascript
86
191
192
+ // 返回一个数组
193
+
87
194
function example () {
88
195
return [1 , 2 , 3 ];
89
196
}
90
-
91
197
var [a, b, c] = example ();
92
198
199
+ // 返回一个对象
200
+
201
+ function example () {
202
+ return {
203
+ foo: 1 ,
204
+ bar: 2
205
+ };
206
+ }
207
+ var { foo, bar } = example ();
208
+
93
209
```
94
210
95
- (3)函数参数的定义
211
+ ** (3)函数参数的定义**
96
212
97
213
``` javascript
98
214
99
- function f ({p1, p2, p3 }) {
215
+ function f ({x, y, z }) {
100
216
// ...
101
217
}
102
218
219
+ f ({x: 1 , y: 2 , z: 3 })
220
+
103
221
```
104
222
105
- (4)函数参数的默认值
223
+ 这种写法对提取JSON对象中的数据,尤其有用。
224
+
225
+ ** (4)函数参数的默认值**
106
226
107
227
``` javascript
108
228
@@ -119,3 +239,49 @@ jQuery.ajax = function (url, {
119
239
};
120
240
121
241
```
242
+
243
+ 指定参数的默认值,就避免了在函数体内部再写` var foo = config.foo || 'default foo'; ` 这样的语句。
244
+
245
+ ** (5)遍历Map结构**
246
+
247
+ 任何部署了Iterator接口的对象,都可以用for...of循环遍历。Map结构原生支持Iterator接口,配合变量的结构赋值,获取键名和键值就非常方便。
248
+
249
+ ``` javascript
250
+
251
+ var map = new Map ();
252
+ map .set (' first' , ' hello' );
253
+ map .set (' second' , ' world' );
254
+
255
+ for (let [key, value] of map) {
256
+ console .log (key + " is " + value);
257
+ }
258
+ // first is hello
259
+ // second is world
260
+
261
+ ```
262
+
263
+ 如果只想获取键名,或者只想获取键值,可以写成下面这样。
264
+
265
+ ``` javascript
266
+
267
+ // 获取键名
268
+ for (let [key] of map) {
269
+ // ...
270
+ }
271
+
272
+ // 获取键值
273
+ for (let [,value] of map) {
274
+ // ...
275
+ }
276
+
277
+ ```
278
+
279
+ ** (6)输入模块的指定方法**
280
+
281
+ 加载模块时,往往需要指定输入那些方法。解构赋值使得输入语句非常清晰。
282
+
283
+ ``` javascript
284
+
285
+ const { SourceMapConsumer , SourceNode } = require (" source-map" );
286
+
287
+ ```
0 commit comments