ES6 容许按照必定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构。javascript
let [a, b, c] = [1, 2, 3];
复制代码
属于“模式匹配”,只要等号两边的模式相同,左边的变量就会被赋予对应的值。java
解构不成功,变量的值就等于undefined
。数组
左边的模式,只匹配一部分的等号右边的数组,解构依然能够成功。markdown
若是等号的右边不是数组(或者严格地说,不是可遍历的结构),那么将会报错。函数
// 报错
let [foo] = 1;
let [foo] = false;
let [foo] = NaN;
let [foo] = undefined;
let [foo] = null;
let [foo] = {};
复制代码
Set 结构,也可使用数组的解构赋值。ui
let [x, y, z] = new Set(['a', 'b', 'c']);
复制代码
具备 Iterator 接口的数据,均可以采用数组形式的解构赋值。spa
function* fibs() {
let a = 0;
let b = 1;
while (true) {
yield a;
[a, b] = [b, a + b];
}
}
let [first, second, third, fourth, fifth, sixth] = fibs();
sixth // 5
复制代码
解构赋值容许指定默认值。code
let [x, y = 'b'] = ['a', undefined]; // x='a', y='b'
复制代码
默认值判断使用严格相等运算符(===
),仅严格等于undefined
生效,‘’
与null
不生效。orm
默认值能够引用解构赋值的其余变量,但该变量必须已经声明。对象
默认值若是是一个表达式,那么这个表达式是惰性求值的,即只有在用到的时候,才会求值。
变量必须与属性同名,才能取到正确的值。
解构失败,变量的值等于undefined
。
对象的方法,能够赋值到某个变量。
// 例一
let { log, sin, cos } = Math;
// 例二
const { log } = console;
log('hello') // hello
复制代码
变量名与属性名不一致,必须写成下面这样。
let { foo: baz } = { foo: 'aaa', bar: 'bbb' };
baz // "aaa"
复制代码
解构也能够用于嵌套结构的对象。
let obj = {
p: [
'Hello',
{ y: 'World' }
]
};
let { p: [x, { y }] } = obj;
x // "Hello"
y // "World"
// p是模式,不是变量,所以不会被赋值。要赋值的写成:let { p, p: [x, { y }] } = obj;
复制代码
解构模式是嵌套的对象,并且子对象所在的父属性不存在,那么将会报错。
// 报错
let {foo: {bar}} = {baz: 'baz'};
复制代码
对象的解构赋值能够取到继承的属性。
属性名能够是表达式。
let arr = [1, 2, 3];
let {0 : first, [arr.length - 1] : last} = arr;
first // 1
last // 3
复制代码
将一个已经声明的变量用于解构赋值,必须很是当心。
// 错误的写法
let x;
{x} = {x: 1};
// SyntaxError: syntax error
// 正确的写法
let x;
({x} = {x: 1});
复制代码
字符串也能够解构赋值。这是由于此时,字符串被转换成了一个相似数组的对象。
const [a, b, c, d, e] = 'hello';
a // "h"
b // "e"
复制代码
解构赋值的规则是,只要等号右边的值不是对象或数组,就先将其转为对象。因为undefined
和null
没法转为对象,因此对它们进行解构赋值,都会报错。
可是数值和布尔值能够先转为对象,所以不会报错。
undefined
就会触发函数参数的默认值。[[1, 2], [3, 4]].map(([a, b]) => a + b);
// [ 3, 7 ]
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]
[1, undefined, 3].map((x = 'yes') => x);
// [ 1, 'yes', 3 ]
复制代码
赋值语句的非模式部分,可使用圆括号。
let b; // 先声明
[(b)] = [3]; // 正确
({ p: (d) } = {}); // 正确
复制代码