解构赋值
- 解构赋值的规则
- 只要等号右边的值不是对象或数组,就先将其转为对象,由于
undefined
和null
无法转为对象,所以对它们进行解构赋值,都会报错.
1. 数组的解构赋值
1.1 解构赋值
从数组和对象中提取值,对变量进行赋值,这被称为解构(Destructuring)
/** ES5的写法 */
let a = 1;
let b = 2;
let c = 3;
/** ES6的写法 */
let [a, b, c] = [1, 2, 3];
1.2. 数组的对应位置变量赋值
本质上,这种写法属于
模式匹配
,只要等号两边的模式相同,左边的变量就会被赋予对应的值,如果解构不成功,变量的值就等于undefined
let [one, [[two], three]] = [1, [[2], 3]];// 解构成功
console.log('one:', one);// one: 1
console.log('two:', two);// two: 2
console.log('three:', three);// three: 3
let [, , six] = [4, 5, 6];// 解构成功
console.log('six:', six);// six: 6
let [seven, , nine] = [7, 8, 9];// 解构成功
console.log('seven:', seven);// seven: 7
console.log('nine:', nine);// nine: 9
let [ten, ...numbers] = [10, 11, 12, 13];// 解构成功
console.log('ten:', ten);// ten: 10
console.log('numbers:', numbers);// numbers: [ 11, 12, 13 ]
let [x, y, ...z] = ['name'];// 解构不成功
console.log('x:', x);// x: name
console.log('y:', y);// y: undefined
console.log('z:', z);// z: []
1.3. 不完全解构
等号左边的模式,只匹配一部分的等号右边的数组
let [one, two] = [1, 2, 3];// 不完全解构
console.log('one:', one);// one: 1
console.log('two:', two);// two: 2
let [four, [five], seven] = [4, [5, 6], 7];// 不完全解构
console.log('four:', four);// four: 4
console.log('five:', five);// five: 5
console.log('seven:', seven);// seven: 7
1.4. 注意
1.4.1. 不可遍历的结构不能被赋值
如果等号右边不是数组,或者严格来说,不是可遍历的结构,那么将会报错,等号右边的值,要么转为对象以后不具备
Iterator
接口,要么本身就不具备Iterator
接口
let [one] = 1;
let [two] = true;
let [three] = NaN;
let [four] = undefined;
let [five] = null;
let [six] = {};
1.4.2. Set
可以使用数组的解构赋值
let [one, two, three] = new Set([1,2,3]);
console.log('one:', one);// one: 1
console.log('two:', two);// two: 2
console.log('three:', three);// three: 3
事实上,只要某种数据结构具有
Iterator
接口,都可以采用数组形式的解构赋值,参见《Generator 函数》
1.4.3. 默认值
解构赋值允许指定默认值
let [one = true] = [];
console.log('one:', one);// one: true
let [two, three = 3] = [2];
console.log('two:', two);// two: 2
console.log('three:', three);// three: 3
1.4.4. ===
严格等于
ES6内部允许使用严格相等运算符
===
,判断一个位置是否有值.所以,如果一个数组成员不严格等于undefined
,默认值是不会生效的
let [one = 1] = [undefined];
console.log('one:', one);// one: 1
let [two = 2] = [null];
console.log('two:', two);// two: null
1.4.5. 默认值是一个表达式
如果默认值是一个表达式,那么这个表达式是惰性求值的,只有在用到的时候,才会求值
function getValue() {
return 1;
}
let [one = getValue()] = [undefined];
console.log(one);// one: 1
上面的代码等价于下边的代码
function getValue() {
return 1;
}
let one;
if ([1][0] === undefined) {
one = getValue();
} else {
one = [1][0];
}
console.log('one:', one);// one: 1
1.4.6. 默认值的其他用法
默认值可以引用解构赋值的其他变量,但是该变量必须已经声明
{
let [one = 1, two = one] = [];
console.log('one:', one);// one: 1
}
{
let [one = 1, two = one] = ['zz'];
console.log('one:', one);// one: zz
console.log('two:', two);// two: zz
}
{
let [one = 1, two = one] = ['zz', 'xx'];
console.log('one:', one);// one: zz
console.log('two:', two);// two: xx
}
{
let [one = two, two = 1] = [];
console.log('one:', one);// ReferenceError: two is not defined
console.log('two:', two);
}