解构赋值
【解构赋值】
数组的解构赋值
原理
ES6 允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构(Destructuring)。
以前,为变量赋值,只能直接指定值。
1 | let a = 1; |
ES6 允许写成下面这样。
1 | let [a, b, c] = [1, 2, 3]; |
上面代码表示,可以从数组中提取值,按照对应位置,对变量赋值。
-
模式(结构)匹配
[] = [1, 2, 3];
-
索引值相同的完成赋值
const [a, b, c] = [1, 2, 3];
-
举例
1
2const [a, [, , b], c] = [1, [2, 3, 4], 5];
console.log(a, b, c); // 1 4 5
数组解构赋值的默认值
(1)默认值的基本用法
1 | const [a, b] = []; |
(2)默认值的生效条件
只有当一个数组成员严格等于 (===) undefined 时,对应的默认值才会生效。
1 | const [a = 1, b = 2] = [3, 0]; // 3 0 |
(3)默认值表达式
如果默认值是表达式,默认值表达式是惰性求值的(即:当无需用到默认值时,表达式是不会求值的)
1 | const func = () => { |
数组解构赋值的应用
(1)arguments
1 | function func() { |
(2)NodeList
1 |
|
(3)函数参数的解构赋值
1 | const array = [1, 1]; |
(4)交换变量的值
1 | let x = 2, y = 1; |
(5)跳过某项值使用逗号隔开
在解构数组时,可以忽略不需要解构的值,可以使用逗号对解构的数组进行忽略操作,这样就不需要声明更多的变量去存值了:
1 | var [a, , , b] = [10, 20, 30, 40]; |
上面的例子中,在 a、b 中间用逗号隔开了两个值,这里怎么判断间隔几个值呢,可以看出逗号之间组成了多少间隔,就是间隔了多少个值。如果取值很少的情况下可以使用下标索引的方式来获取值。
(6)剩余参数中的使用
通常情况下,需要把剩余的数组项作为一个单独的数组,这个时候我们可以借助展开语法把剩下的数组中的值,作为一个单独的数组,如下:
1 | var [a, b, ...rest] = [10, 20, 30, 40, 50]; |
在 rest 的后面不能有 逗号 不然会报错,程序会认出你后面还有值。...rest
是剩余参数的解构,所以只能放在数组的最后,在它之后不能再有变量,否则则会报错。
必须要分号的两种情况
1 | // 1. 立即执行函数 |
对象的解构赋值
原理
对象的解构和数组基本类似,对象解构的变量是在 {}
中定义的。对象没有索引,但对象有更明确的键,通过键可以很方便地去对象中取值。在 ES6 之前直接使用键取值已经很方便了:
1 | var obj = { name: 'imooc', age: 7 }; |
但是在 ES6 中通过解构的方式,更加简洁地对取值做了简化,不需要通过点操作增加额外的取值操作。
1 | var obj = { name: 'imooc', age: 7 }; |
在 {}
直接声明 name 和 age 用逗号隔开即可得到目标对象上的值,完成声明赋值操作。
- 模式(结构)匹配
{} = {};
- 属性名相同的完成赋值
const {name, age} = {name: 'jerry', age: 18};
或const {age, name} = {name: 'jerry', age: 18};
对象解构赋值的默认值
-
对象的属性值严格等于 undefined 时,对应的默认值才会生效。
-
如果默认值是表达式,默认值表达式是惰性求值的。
对象的默认值和数组的默认值一样,只能通过严格相等运算符(===)来进行判断,只有当一个对象的属性值严格等于 undefined
,默认值才会生效。
1 | var {a = 10, b = 5} = {a: 3}; // a = 3, b = 5 |
所以这里的第二项 b 的值是默认值,第三项的 null === undefined
的值为 false,所以 b 的值为 null。
重命名属性
在对象解构出来的变量不是我们想要的变量命名,这时我们需要对它进行重命名。
1 | var {a:x = 8, b:y = 3} = {a: 2}; |
这里把 a 和 b 的变量名重新命名为 x 和 y。
对象解构赋值的应用
(1)对象作为函数参数
1 | // 之前 |
(2)复杂的嵌套(主要是缕清逻辑关系即可)
1 | const obj = { |
(3)剩余参数中的使用
在对象的解构中也可以使用剩余参数,对对象中没有解构的剩余属性做聚合操作,生成一个新的对象。
1 | var {a, c, ...rest} = {a: 1, b: 2, c: 3, d: 4} |
对象中的 b、d 没有被解构,通过剩余参数语法把没有解构的对象属性聚合到一起形成新的对象。
注意点
(1)如果要将一个已经声明的变量用于解构赋值,必须非常小心。
1 | // 错误的写法 |
上面代码的写法会报错,因为 JavaScript 引擎会将{x}
理解成一个代码块,从而发生语法错误。只有不将大括号写在行首,避免 JavaScript 将其解释为代码块,才能解决这个问题。
1 | // 正确的写法 |
上面代码将整个解构赋值语句,放在一个圆括号里面,就可以正确执行。关于圆括号与解构赋值的关系,参见下文。
(2)解构赋值允许等号左边的模式之中,不放置任何变量名。因此,可以写出非常古怪的赋值表达式。
1 | ({} = [true, false]); |
上面的表达式虽然毫无意义,但是语法是合法的,可以执行。
(3)由于数组本质是特殊的对象,因此可以对数组进行对象属性的解构。
1 | let arr = [1, 2, 3]; |
上面代码对数组进行对象解构。数组arr
的0
键对应的值是1
,[arr.length - 1]
就是2
键,对应的值是3
。
字符串的解构赋值
既可以用数组的形式来解构赋值,也可以用对象的形式来解构赋值。
1 | // 数组形式解构赋值 |
数值和布尔值的解构赋值
只能按照对象的形式来解构赋值。
(会先自动将等号右边的值转为对象)
1 | // 先来复习一下将数值和布尔值转化为对象 |
知道有这回事即可,一般都用不到,因为没太大意义。
undefined 和 null 没有解构赋值
由于 undefined 和 null 无法转为对象,所以对它们进行解构赋值,都会报错。
小结
本节讲解了 ES6 解构赋值的使用方法,总结下来一共有以下几点:
- 解构赋值一般针对对象和数组,如果解构对象是
undefined
或是null
都会报错; - 默认值的生效条件是,只有当解构的对象的值是严格模式下的
undefined
的情况下,默认值才会生效; - 可以不借助中间变量来交换两个值;
- 在解构复杂的数据解构时,注意声明的对象要和目标的对象有着相同的解构形式,才能去解构目标对象。