1、数组的解构赋值
let [a = 'a', b = 'b'] = ['undefined',undefined]; //[undefined, 'b'];
let [x = 1] = null // null 因为null === undefined false;
ES6内部使用严格相等运算符(===),判断一个位置是否有值,只有数组成员与undefined严格相等,默认值才生效
function fn() {
console.log('执行了')
}
let [x = fn()] = [1]; //[x = 1]
因为 x 取到了值,所以没有执行fn(),若 let [x = fn()] = [undefined],则执行默认值,即fn()函数;
let [x = 1, y = x] = [] // x = 1, y = 1;
let [x = 1, y = x] = [2] // x = 2, y = 2;
let [x = 1, y = x] = [1, 2] // x = 1, y = 2;
let [x = y, y = 1] = [] // ReferenceError: y is not defined
上面最后一个表达式报错,是由于x = y 使用了 y 作为默认值,而 y 没有声明
2、对象的解构赋值
- 对象的解构,与属性的顺序无关,按照属性名进行取值,k - v 保持一致;
- 数组的解构,与变量位置有关,按照次序进行取值;
let {foo, bar} = {
bar: 'aaa',
foo: 'bbb'
}; // foo: 'bbb' bar: 'aaa'
let { baz } = {foo: 'aaa', bar: 'bbb'}; //undefined
变量baz没有对应的同名属性导致解构失败,返回undefined,如果变量名与属性名不一致,需写成如下方式
let {foo: baz} = { foo: 'aaa', baz: 'bbb' }; // baz:'aaa'
let { foo: foo, bar: bar} = { foo: 'aaa', bar: 'bbb' } // foo:'aaa', bar:'bbb'
let {foo: baz} = {foo:'aaa',bar: 'bbb'} // baz: 'aaa'; foo: error:foo is not defined;
上述代码中,foo是匹配的模式,baz才是变量,真正被赋值时baz,而不是模式foo,这说明 对象的解构赋值的内部机制,是找到同名属性给对应的变量赋值,真正被赋值的是前者,而不是后者;
嵌套赋值
let obj = {};
let arr = [];
({ foo: obj.prop, bar: arr[0] } = {foo: 123, bar: true})
obj //{prop:123,arr:[true]}
const obj1 = {};
const obj2 = {foo: 'bar'};
object.setPrototypeOf(obj1,obj2) //obj1的原型对象赋给obj2
const { foo } = obj1;
foo // "bar"
默认值
对象的解构也可以有默认值,默认值生效的条件是,对象的属性值严格等于undefined
var { x = 3 } = { x: undefined };
x // 3
var { x = 3 } = { x: null };
x // null
注意:
// 错误写法:
let x;
{x} = {x:1}
// SyntaxError: syntax error
上述写法中js引擎会把{x}理解成一个代码块,从而产生语法错误,应避免在行首出现{}
// 正确写法:
let x;
({x} = {x:1});
let arr = [1, 2, 3];
let {0: first, [arr.length - 1]: last} = arr;
first // 1
last // 3
3、字符串的解构赋值
const [a, b, c, d, e] = 'hello';
a // 'h'
b // 'e'
c // 'l'
d // 'l'
e // 'o'
// 对属性解构赋值
let { length: len } = 'hello';
len // 5
4、数值和布尔值的解构赋值
let {toString : s} = 123;
s === Number.prototype.toString; // true;
let {toString: s} = true;
s === Boolean.prototype.toString // true;
let {prop: s} = undefined; // TypeError;
let {prop: y} = null; // TypeError;
解构赋值时,等号右边的值不是数组或对象,先将其转化为对象,undefined和null无法转化为对象,所以对他们进行解构赋值失败。
5、函数参数的解构赋值
[[1, 2], [3, 4]].map(([a, b]) => a + b); //[3, 7]
函数参数的解构也可以使用默认值
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]
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() //[undefined, undefined];
上述代码给move参数指定默认值,而不是给x, y指定默认值,
undefined触发函数参数的默认值[1, undefined, 3].map((x = 'yes') => x); //[1, 'yes', 3]
解构赋值用途
- 交换变量的值
let x = 1;
let y = 2;
[x, y] = [y, x];
- 从函数返回多个值
// 返回一个数组
function example() {
return [1, 2, 3]
}
let [a, b, c] = example();
// 返回一个对象
function example() {
return {
foo: 1,
bar: 2
}
}
let {foo, bar} = example();
- 函数参数的定义
// 参数是一组有次序的值
function f([x, y, z]){ ... };
f([1, 2, 3])
// 参数是一组无次序的值
function f({x, y, z}) { ... }
f({z: 3, y: 2, x: 1});
- 提取JSON数据
let jsonData = {
id: 42,
status: 'ok',
data: [1, 2]
};
let { id, status, data: number } = jsonData;
console.log(id, status, number);
// 42, 'ok', [1, 2]
- 遍历Map结构
const map = new Map();
map.set('first', 'hello');
map.set('second', 'world');
for(let [key, value] of map) {
console.log(key + 'is' + 'value')
}
// first is hello
// second is world
只获取键名
// 只获取键名
for (let [key] of map){
// ...
}
// 只获取键值
for (let [, value] of map) {
// ...
}