ES6 允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构(Destructuring)。解构分为以下几种:
数值解构
1. 情况1:少 对 多 ——-解构成功
let [ , , third] = ["foo", "bar", "baz"];
third // "baz"
//只输出有赋值的变量
let [head, ...tail] = [1, 2, 3, 4];
head // 1
tail // [2, 3, 4]
let [x, y, ...z] = ['a'];
x // "a"
y // undefined
z // []
-----解构成功,属于不完全解构
let [a, [b], d] = [1, [2, 3], 4];
a // 1
b // 2
d // 4
2. 情况2: 多 对 少 ——–解构不成功
let [foo] = [];
let [bar, foo] = [1];
两个foo输出都是undefined
如果等号的右边可遍历的结构,那么将会报错。
// 报错
let [foo] = 1;
let [foo] = false;
let [foo] = NaN;
let [foo] = undefined;
let [foo] = null;
let [foo] = {};//不具备可以遍历的Iterator接口
对象解构
1.一一对应关系,而且被赋值的是后者,
let { foo: baz } = { foo: "aaa", bar: "bbb" };
baz // "aaa"
foo // error: foo is not defined
2.数组本质是特殊的对象,因此可以进行对象属性的结构
let arr = [1, 2, 3];
let {0 : first, [arr.length - 1] : last} = arr;
first // 1
last // 3
方括号这种写法,属于“属性名表达式”,
字符串解构
原理:字符串被转换成了类似数组的对象,可以按照对象解构理解使用
数值和布尔值的结构赋值
解构赋值时,如果等号右边是数值和布尔值,则会先转为对象。
let {toString: s} = 123;
s === Number.prototype.toString // true
s//undefined
let {toString: s} = true;
s === Boolean.prototype.toString // true
除了NULL和undefined以外任何值都具有toString()方法,因此变量 s 都能取到值。
解构赋值的规则是,只要等号右边的值不是对象,就先将其转为对象。由于 undefined 和 null 无法转为对象,所以对它们进
行解构赋值,都会报错。
let { prop: x } = undefined;
// TypeError
let { prop: y } = null;
// TypeError
NAN和其他对象一样;
//ReferenceError: NAN is not defined
函数参数解构
函数参数的解构也可以使用默认值。
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 的值。如果解构失败, 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]
上面代码是为函数 move 的参数指定默认值,而不是为变量 x 和 y 指定默认值,所以会得到与前一种写法不同的结果。
undefined 就会触发函数参数的默认值。
[1, undefined, 3].map((x = 'yes') => x);
// [ 1, 'yes', 3 ]
解构允许设置默认值
ES6 内部使用严格相等运算符( === ),判断一个位置是否有值。所以,如果一个数组成员不严格等于 undefined ,
默认值是不会生效的。
let [x = 1] = [undefined];
x // 1
let [x = 1] = [null];
x // null
function f() {
console.log('aaa');
}
let [x = f()] = [1]
x//1 表达式只有用到才会赋值
默认值可以引用已经声明并且解构赋值的其他变量,
注意
由于let和const禁止重复声明的,所以解构的时候一样。但是只要没有第二个let或者const,就不会有问题了。
如果要将一个已经声明的变量用于解构赋值,必须非常小心。
// 错误的写法
let x;
{x} = {x: 1};
// SyntaxError: syntax error
//JavaScript引擎会将 {x} 理解成一个代码块,从而发生语法错误
// 正确的写法
({x} = {x: 1});
圆括号尽量少用,会引起不必要的报错
使用解构的好处
在于数据的接受,处理和传输