数组的解构赋值
1.基本用法
ES6允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构.
可以从数组中提取值,按照位置的对应关系对变量赋值.
本质上,这种写法属于模式匹配,只要等号两边的模式相同,左边的变量就会被赋予对应的值.
var [a, b, c] = [1, 2, 3];
var [d, ...array] = [1, 2, 3];
console.log(a);
console.log(b);
console.log(c);
console.log(d);
console.log(array); // [2, 3]
let [foo, [[bar], baz]] = [1, [[2], 3]];
console.log(foo);
console.log(bar);
console.log(baz);
let [, , third] = [1, 2, 3];
console.log(third); // 3
2.如果结构不成功,变量的值就等于undefined.
另一种情况是不完全解构,即等号左边的模式只匹配等号右边数组的一部分,
这种情况下,解构依然可以成功.
如果等号的右边不是数组(或者严格的说,不是可遍历的结构),那么将会报错.
let [bar1, foo1] = [1];
console.log(bar1); // 1
console.log(foo1); // undefined
3.默认值
解构赋值允许指定默认值
注意,ES6内部使用严格相等运算符(===)判断一个位置是否有值,所以,如果一个数组成员
不严格等于undefined,默认值是不会生效的.
var [foo = true] = [];
console.log(foo); // true
var [x, y = 'b'] = ['a'];
console.log(x); // 'a'
console.log(y); // 'b'
var [xx, yy = 'b'] = ['a', undefined];
console.log(xx); // 'a'
console.log(yy); // 'b'
// 如果一个数组成员是null,默认值就不会生效,因为null不严格等于undefined
var [xxx = 1] = [undefined];
var [yyy = 1] = [null];
console.log(xxx); // 1
console.log(yyy); // null
// 如果默认值是一个表达式,那么这个表达式是惰性求值的,即只有在用到的时候才会求值
// 因为x能取到值,所以函数f根本不会执行
function f() {
console.log('aaa');
}
let [xxxx = f()] = [1];
// 默认值可以引用解构赋值的其他变量,但该变量必须已经声明
let [x = 1, y = x] = [];
console.log(x); // 1
console.log(y); // 1
let [xx = 1, yy = xx] = [2];
console.log(xx); // 2
console.log(yy); // 2
let [xxx = 1, yyy = xxx] = [1, 2];
console.log(xxx); // 1
console.log(yyy); // 2
let [xxxx = yyyy, yyyy = 1] = []; // ReferenceError
console.log(xxxx); // undefined
console.log(yyyy); // 1
对象的解构赋值
1.解构不仅可以用于数组,还可以用于对象.
对象的解构与数组有一个重要的不同,数组的元素是按次序排列的,变量的取值由它的位置决定.
而对象的属性没有次序,变量必须与属性同名,才能取到正确的值.
也就是说,对象的解构赋值的内部机制,是先找到同名属性,然后再赋给对应的变量.
真正被赋值的是后者,而不是前者.
这实际上说明,对象的解构赋值是以下形式的简写.
var { foo: foo, bar: bar } = {
foo: 'aaa',
bar: 'bbb'
};
var { foo, bar } = {
foo: 'aaa',
bar: 'bbb'
};
console.log(foo); // 'aaa'
console.log(bar); // 'bbb'
// 如果变量名与属性名不一致,必须写成下面这样
var { foo1: baz1 } = {
foo1: 'aaa',
bar: 'bbb'
};
// console.log(foo1); // Uncaught ReferenceError: foo1 is not defined
console.log(baz1); // 'aaa'
let { first: f, last: l } = { first: 'hello', last: 'world' };
console.log(f); // 'hello'
console.log(l); // 'world'
2.和数组一样,解构也可以用于嵌套解构的对象
// 注意,这时p是模式,不是变量,因此不会被赋值
var obj = {
p: [
'hello',
{ y: 'wrold' }
]
};
var { p: [x, { y }] } = obj;
console.log(x); // 'hello'
console.log(y); // 'world'
// 只有line是变量,loc和start都是模式,不会被赋值
var node = {
loc: {
start: {
line: 1,
column: 5
}
}
};
var { loc: { start: { line } } } = node;
console.log(line);
// 嵌套赋值
let obj1 = {};
let arr = [];
({ foo: obj1.prop, bar: arr[0] } = { foo: 123, bar: true });
console.log(obj1); // {prop:123}, obj1.prop被赋值123,所以obj1是一个对象
console.log(arr); // [true], arr[0]被赋值为true,所以arr是一个数组