解构是一种快速为变量赋值的简洁语法,本质上仍然是为变量赋值,分为数组解构、对象解构两大类型。
基本语法:
const/let/var [变量1, 变量2, 变量3...] = [1, 2, 3...];
数组的解构赋值,只需要先使用声明符const
/let
/var
来声明变量,随后进行解构。在解构赋值时,左侧的变量会与右侧的数组按顺序一一对应,完成赋值。
比如:
let arr = [11, 22, 33, 44];
let [a, b, c, d] = arr;
相当于:
let arr = [11, 22, 33, 44];
let a = arr[0];
let b = arr[1];
let c = arr[2];
let d = arr[3];
但是要注意,在进行数组解构之前,前一条语句必须加分号;
。
当数组解构时,变量与参数不匹配,那么能对应上的变量则成功赋值,不能匹配上的则被赋值为undefined。
比如:
let [a, b, c] = [1, 2];
那么a和b成功赋值,但是c被赋值为undefined。
而对于:
let [a, b, c] = [1, 2, 3, 4];
那么a,b,c成功赋值为1,2,3。多余的数字则会被忽略。
当我们只需要数组中的部分值,也可以省略部分变量,只需要将不需要的值对应的位置空开即可。
比如:
let [a, b, c] = [1, 2, 3, 4];
现在想要忽略数字2,让a = 1
,b = 3
, c = 4
。
let [a, , b, c] = [1, 2, 3, 4];
在上述语法中,我们将2对应的位置空开了,这样就可以完成数组解构的同时只取出想要的值。
数组解构也可以配合展开运算符来使用,这样当有盈余的变量,就会整合为一个数组,赋值到一个变量中。
示例:
let [a, b, ...c] = [1, 3, 5, 7, 9, 11, 13];
此时a = 1
, b = 3
。而多余的所有数字都会整合为一个数组,赋值给c。即c=[5, 7, 9, 11, 13]
。
注意:
在这种情况下,c得到一定是一个数组。
当没有值赋给c,那么c就是一个空数组;如果只有一个数据赋值给c,c就是只有一个数据的数组。
如果不确定你的变量能接收到几个值,但是又不希望变量变为undefined,此时就可以为解构赋值的变量设置默认值:
示例:
let [a = 444, b = 555, c = 666, d = 777] = [1, 3];
通过上述语法,a和b可以通过解构赋值得到数据,所以a = 1
, b = 3
;而c和d无法通过解构获得值,此时c和d会获得默认值:c = 666
,d = 777
。
对于多维数组,其解构也就是在对应的位置添上方括号,然后将变量与数值一一对应。
示例:
let [a, [b, c], d] = [1, [5, 6], 2];
此时变量与数据一一对应:a = 1
,b = 5
, c = 6
, d = 2
。
总结:
- 赋值运算符
=
左侧的[]
用于批量声明变量,右侧数组的单元值将被赋值给左侧的变量- 变量的顺序对应数组单元值的位置依次进行赋值操作,允许有空缺
- 变量的数量大于单元值数量时,多余的变量将被赋值为
undefined
- 变量的数量小于单元值数量时,可以通过
...
获取剩余单元值,但只能置于最末位- 允许初始化变量的默认值
- 支持多维解构赋值
对象解构是将对象属性和方法快速批量赋值给一系列变量的简洁语法,其与数组解构大体一致。
语法:
let/const/var {key1, key2, key3 ...} = {key1: val1, key2: val2, key3: val3 ...}
数组解构中,我们只需要将变量与数据的位置一一对应,因为每个数据都有固定的位置与下标。而对象内部的属性时无序的,所以不能通过位置来一一对应。为了在解构赋值时可以精确匹配数据,那就要找出每一个属性独一无二的特征:属性名
。
由于对象中每一个属性的的属性名都不同,所以我们要通过属性名来匹配数据。所以:对象解构时,左侧被赋值的变量名必须和右侧的属性名完全一致。
这也就是为什么上面的语句中,左侧变量和右侧属性的变量名完全一致。
如果按照基本语法来赋值,那么变量名称就被完全局限了,于是JavaScript在对象解构时也提供了方法,让用户可以修改被赋值的变量的名称。
语法:
let/const/var {key1: newname1, key2: newname2...} = {key1: val1, key2: val2...}
由于与右侧属性名相同的变量名用于定位数据,那么这里的key1,key2是不能删改的,但是又要引入想要的变量名,于是就在保留原先变量名的基础上,添加一个你想要的变量名:与属性值对应的变量名: 你想要的变量名
。
比如上述示例代码中,赋值后newname1 = val1
, newname2 = val2
,后续用户就可以使用新的变量名了。
在数组解构中,如果变量位置无法与参数匹配,就会被赋值为undefined;而在对象解构中,如果变量名无法和参数匹配,也会被赋值为undefined。
示例:
const user = {
name: '小明',
age: 18
};
const {friend, name, age,} = user
console.log(name) // 小明
console.log(age) // 18
console.log(friend)//undefined
上述代码,user这个对象中有name和age两个属性,在解构赋值时,我们多输入了一个friend变量,此时friend虽然放在第一位,但是没有与之对应的属性,最后被赋值为了undefined。
- 赋值运算符
=
左侧的{}
用于批量声明变量,右侧对象的属性值将被赋值给左侧的变量- 对象属性的值将被赋值给与属性名相同的变量
- 对象中找不到与变量名一致的属性时变量值为
undefined
- 允许初始化变量的默认值,属性不存在或单元值为
undefined
时默认值才会生效
那么当对象内嵌套了一个对象,应该如何解构赋值?
尝试对以下对象解构赋值:
let zhangsan = {
name: "张三",
age: 18,
height: "188cm",
father: {
Tel: "123xxxx4567",
address: "河北"
}
}
在zhangsan
这个对象中,有三个属性:name
,age
,height
以及一个嵌套对象father
。
我们看看这一种解构方式:
let {name, age, height, {Tel, address}} = zhangsan
这种方式,看似符合逻辑,但是这是沿袭了数组解构的思想,数组中嵌套的数组,位置是固定的,而对象的属性位置是不定的,也就是说{Tel, address}
这个嵌套的解构,它找不到想要的对象,在嵌套解构之前,我们要对内部嵌套的解构声明:解构哪一个对象。也就是说要指明{Tel, address}
的对象是father
。
正确语法:
let {name, age, height, father: {Tel, address}} = zhangsan
在嵌套解构时,解构内部的对象时,要用{ 对象名:{属性值} }
来声明解构哪一个子对象。