ES6 允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构
(Destructuring)。
解构赋值是对赋值运算符的扩展。他针对数组或者对象进行模式匹配,然后对其中的变量进行赋值。就是按照视觉上的一一对应关系进行赋值。
数组是按照位置来进行结构的,变量名可随意,所以与变量名字无关,赋值的顺序是数组索引的顺序
顺序:
let [a,b,c] = [1,2,3];
console.log(a,b,c); // 1,2,3
乱序:
let [b,a,c] = [1,2,3];
console.log(a,b,c); // 2,1,3
对象是按照属性名字进行结构的,所以与变量的位置无关,但变量名必须是对象中的属性名
顺序:
let {name, num} = { name:"bull", num:"1" };
console.log(name, num); // bull, 1
乱序:
let {num, name} = {name:"cow",num:"2"};
console.log(num, name); // 2, cow
1、数组
let [a, [b, c], d] = [1, [2, 3], 4];
console.log(a, b, c, d) // 1, 2, 3, 4
2、对象
let obj = {
animal: {
cow: {
name: 'xx'
}
}
};
// 只解构第二层数据 - cow
let {animal: { cow }} = obj
console.log(animal, cow) // undefined, {name: 'xx'}
// 只解构第三层数据 - name
let {animal: {cow: { name }}} = obj
console.log(name) // xx
// 解构嵌套的每层的数据
let {animal, animal: { cow }, animal: { cow: { name }}} = obj
console.log(aniaml, cow, name) // {cow: {name:'xx'}}, {name:'xx'}, xx
1、只解构数组前2个元素
let [a, b] = [1, 2, 3];
console.log(a, b, c) // 1, 2
2、数组的多层嵌套,只解构嵌套数组中的其中一个
let [a, [b], d] = [1, [2, 3], 4];
console.log(a, b, d) // 1, 2, 4
3、注意这是完全解构,但前两个元素虽然解构了,但是不要了,因为位置对应的关系,所以必须有两个占位的,这样才能拿到第三个元素
let [, , c] = [1, 2, 3];
console.log(c) // 3
4、解构出一个找不到的元素,因为前三个元素都能对应找到,而第四个找不到,但是已经声明了,没有值
let [a, b, c, d] = [1, 2, 3]
console.log(a, b, c, d) // 1, 2, 3, undefined
const school = {
name: "TUST",
location: "Tian'Jin"
};
let { name: schoolName, location } = school;
console.log(name, schoolName, location) // undefined, TUST, Tian'Jin 属性名name已经被重命名为schoolName,所以输出undefined
1、数组
a,b,c在左边都先给了个默认值,如果没有默认值就是undefined
let [a=0, b=0, c=6] = [1, 2];
console.log(a, b, c) // 1, 2, 6
2、对象
let {name ='xx2'} ={name:'xx', age:18}
console.log(name) //xx
对象属性里有name,取到了name值并且重命名为name2,其默认值为xx2
let {name: name2='xx2'} ={name:'xx', age:18}
console.log(name2) //xx
对象属性里没有sex,但其有默认值为man
let {name: {sex='man'}} = {name:'xx',age:18}
console.log(sex) // man
当有多余的值不想一一赋值的时候可以使用剩余参数,即将这些解构没有对应上的值全部放进一个数组
let [head, ...tail] = [1, 2, 3, 4];
head // 1
tail // [2, 3, 4]
let [x, y, ...z] = ['a'];
x // "a"
y // undefined
z // []
字符串也可以解构赋值。这是因为此时,字符串被转换成了一个类似数组的对象
const [a, b, c, d, e] = 'hello';
a // "h"
b // "e"
c // "l"
d // "l"
e // "o"
类似数组的对象都有一个length
属性,因此还可以对这个属性解构赋值
let {length : len} = 'hello';
len // 5
函数add
的参数表面上是一个数组,但在传入参数的那一刻,数组参数就被解构成变量x
和y
。对于函数内部的代码来说,它们能感受到的参数就是x
和y
function add([x, y]){
return x + y;
}
add([1, 2]); // 3
[[1, 2], [3, 4]].map(([a, b]) => a + b);
// [ 3, 7 ]
2、函数参数
的解构
也可以使用默认值
函数move
的参数是一个对象,通过对这个对象进行解构,得到变量x
和y
的值。如果解构失败,x
和y
等于默认值
function move({x = 0, y = 0} = {}) {
return [x, y];
}
move({x: 3, y: 8}); // [3, 8]
move({x: 3}); // [3, 0]
move({}); // [0, 0]
move(); // [0, 0]
注意:下面代码是为函数move
的参数指定默认值,而不是为变量x
和y
指定默认值,所以会得到与前一种写法不同的结果。
function move({x, y} = { x: 0, y: 0 }) {
return [x, y];
}
move({x: 3, y: 8}); // [3, 8]
move({x: 3}); // [3, undefined]
move({}); // [undefined, undefined]
move(); // [0, 0]
undefined
就会触发函数参数的默认值[1, undefined, 3].map((x = 'yes') => x);
// [ 1, 'yes', 3 ]
解构赋值时,如果等号右边
是数值和布尔值,则会先转为对象,
数值和布尔值的包装对象都有toString
属性,因此变量s
都能取到值
let {toString: s} = 123;
s === Number.prototype.toString // true
let {toString: s} = true;
s === Boolean.prototype.toString // true
undefined
和null
解构赋值的规则是,只要等号右边的值不是对象或数组,就先将其转为对象。
由于undefined
和null
无法转为对象,所以对它们进行解构赋值,都会报错。
let { prop: x } = undefined; // TypeError
let { prop: y } = null; // TypeError