ES6 允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构。
let [a, b] = [1, 2];
let {c, d} = {c: 3, d: 4};
console.log(a); //1
console.log(b); //2
console.log(c); //3
console.log(d); //4
数组的解构赋值
let [a, b] = [1, 2];
console.log(a); //1
console.log(b); //2
这种写法属于“模式匹配”,只要等号两边的模式相同,左边的变量就会被赋予对应的值。
let [a, [[b], c]] = [1, [[2], 3]];
console.log(a); //1
console.log(b); //2
console.log(c); //3
let [, , d] = [4, 5, 6];
console.log(d); //6
let [e, ...f] = [7, 8, 9];
console.log(e); //7
console.log(f); //[8, 9]
如果解构不成功,变量的值就等于undefined。
let [a] = [];
console.log(a); //undefined
let [b, c] = [1];
console.log(b); //1
console.log(c); //undefined
let [d, e, ...f] = [2];
console.log(d); //2
console.log(e); //undefined
console.log(f); //[]
另一种情况是不完全解构,即等号左边的模式,只匹配一部分的等号右边的数组。这种情况下,解构依然可以成功。
let [a, b] = [1, 2, 3];
console.log(a); //1
console.log(b); //2
let [c, [d], e] = [4, [5, 6], 7];
console.log(c); //4
console.log(d); //5
console.log(e); //7
如果等号的右边不是可遍历的结构,那么将会报错。
// 报错
let [a] = 1;
let [b] = false;
let [c] = NaN;
let [d] = undefined;
let [e] = null;
let [f] = {};
解构赋值允许指定默认值。
let [a = 1] = [];
console.log(a); //1
只有当一个数组成员严格等于(===)undefined,默认值才会生效。
let [a = 1] = [undefined];
let [b = 2] = [null];
console.log(a); //1
console.log(b); //null
默认值可以引用解构赋值的其他变量,但该变量必须已经声明。
let [a = 1, b = a] = [];
console.log(a); //1
console.log(b); //1
//报错
let [c = d, d = 1] = [];
对象的解构赋值
let {a, b} = {a: 1, b: 2};
console.log(a); //1
console.log(b); //2
对象的解构与数组有一个重要的不同。数组的元素是按次序排列的,变量的取值由它的位置决定;而对象的属性没有次序,变量必须与属性同名,才能取到正确的值。
let {b, a} = {a: 1, b: 2};
console.log(a); //1
console.log(b); //2
如果没有对应的同名属性则解构失败,变量的值等于undefined。
let {a} = {b: 1, c: 2};
console.log(a); //undefined
如果变量名与属性名不一致,必须写成下面这样。
let {a: b} = {a: 1};
console.log(b); //1
与数组一样,解构也可以用于嵌套结构的对象。
let obj = {
arr: [
1,
{b: 2}
]
};
let {arr: [a, {b}]} = obj;
console.log(a); //1
console.log(b); //2
注意,这时arr是模式,不是变量,因此不会被赋值。如果arr也要作为变量赋值,可以写成下面这样。
let obj = {
arr: [
1,
{b: 2}
]
};
let {arr, arr: [a, {b}]} = obj;
console.log(a); //1
console.log(b); //2
console.log(arr); //[1, {b: 2}]
如果解构模式是嵌套的对象,而且子对象所在的父属性不存在,那么将会报错。
//报错
let {arr: {a}} = {a: 1};
对象的解构赋值可以取到继承的属性。
let obj1 = {};
let obj2 = {a: 1};
obj1.__proto__ = obj2;
let {a} = obj1;
console.log(a); //1
对象的解构也可以指定默认值。默认值生效的条件是,对象的属性值严格等于(===)undefined。
let {a = 1} = {};
console.log(a); //1
let {b = 2} = {b: null};
console.log(b); //null
如果要将一个已经声明的变量用于解构赋值,必须非常小心。
let a;
{a} = {a: 1}; //报错
上面代码的写法会报错,因为 JavaScript 引擎会将{x}理解成一个代码块,从而发生语法错误。只有不将大括号写在行首,避免 JavaScript 将其解释为代码块,才能解决这个问题。
let a;
({a} = {a: 1}); //不报错
console.log(a); //1
上面代码将整个解构赋值语句,放在一个圆括号里面,就可以正确执行。
字符串的解构赋值
字符串也可以解构赋值。这是因为此时,字符串被转换成了一个类似数组的对象。
let [a, b, c, d, e] = "hello";
console.log(a); //h
console.log(b); //e
console.log(c); //l
console.log(d); //l
console.log(e); //o
类似数组的对象都有一个length属性,因此还可以对这个属性解构赋值。
let {length} = "hello";
console.log(length); //5
数值和布尔值的解构赋值
解构赋值时,如果等号右边是数值和布尔值,则会先转为对象。
let {toString: a} = 123;
console.log(a === Number.prototype.toString); //true
let {toString: b} = true;
console.log(b === Boolean.prototype.toString); //true
上面代码中,数值和布尔值的包装对象都有toString属性,因此变量s都能取到值。
解构赋值的规则是,只要等号右边的值不是对象或数组,就先将其转为对象。由于undefined和null无法转为对象,所以对它们进行解构赋值,都会报错。
let {a} = undefined; //报错
let {b} = null; //报错
函数参数的解构赋值
函数的参数也可以使用解构赋值。
function fun([a, b]){
console.log(a + b);
}
fun([1, 2]); //3
函数参数的解构也可以使用默认值。
function fun({a = 1, b = 2} = {}){
return [a, b];
}
fun({a: 3, b: 4}); //[3, 4]
fun({a: 3}); //[3, 2]
fun(); //[1, 2]
注意,下面的写法会得到不一样的结果。
function fun({a, b} = {a: 1, b: 2}){
return [a, b];
}
fun({a: 3, b: 4}); //[3, 4]
fun({a: 3}); //[3, undefined]
fun({}); //[undefined, undefined]
fun(); //[1, 2]
用途
交换变量的值。
let a = 1,
b = 2;
[a, b] = [b, a];
console.log(a); //2
console.log(b); //1
从函数返回多个值。
//返回一个数组
function fun(){
return [1, 2, 3];
}
let [a, b, c] = fun();
console.log(a); //1
console.log(b); //2
console.log(c); //3
//返回一个对象
function fun(){
return {
a: 1,
b: 2
};
}
let {a, b} = fun();
console.log(a); //1
console.log(b); //2
将一组参数与变量名对应起来。
//参数是一组有次序的值
function fun([a, b, c]){
console.log(a + b + c);
}
fun([1, 2, 3]); //6
//参数是一组无次序的值
function fun({a, b, c}){
console.log(a + b + c);
}
fun({c: 3, b: 2, a: 1}); //6
指定函数参数的默认值。
function fun({a = 0, b = 0, c = 0} = {}){
console.log(a + b + c);
}
fun({a:1}); //1
fun({a:1, b: 2}); //3
fun({}); //0
fun(); //0
本文介绍了ES6的解构赋值,包括数组、对象、字符串、数值和布尔值的解构赋值,以及函数参数的解构赋值。阐述了不同类型解构赋值的规则、默认值设定等,还提及解构赋值在交换变量值、从函数返回多值等方面的用途。

334

被折叠的 条评论
为什么被折叠?



