/* 绑定模式:变量同用一个声明let/const */
/* 数组 */
const [a, b] = array;
let [a, , b] = array;
const [a = aDefault, b] = array;
let [a, b, ...rest] = array;
const [a, , b, ...rest] = array;
let [a, b, ...{ pop, push }] = array;
const [a, b, ...[c, d]] = array;
/* 对象 */
const { a, b } = obj;
let { a: a1, b: b1 } = obj;
const { a: a1 = aDefault, b = bDefault } = obj;
let { a, b, ...rest } = obj;
const { a: a1, b: b1, ...rest } = obj;
let { [key]: a } = obj;
/* 赋值模式:变量的声明各自独立 */
let a, b, a1, b1, c, d, rest;
let pop, push;
[a, b] = array;
[a, , b] = array;
[a = aDefault, b] = array;
[a, b, ...rest] = array;
[a, , b, ...rest] = array;
[a, b, ...{ pop, push }] = array;
[a, b, ...[c, d]] = array;
({ a, b } = obj); // 必须加上 ()
({ a: a1, b: b1 } = obj);
({ a: a1 = aDefault, b = bDefault } = obj);
({ a, b, ...rest } = obj);
({ a: a1, b: b1, ...rest } = obj);
将可迭代对象解构,赋值给数组模式里对应位置上的变量。
let [a, b] = [1, 2];
let [a, [b, c], [d], e] = [1, [2, 3], [4], 5];
let [a, b] = [1, 2, 3] // a=1,b=2
let [a, , b] = [1, 2, 3, 4] // a=1,b=3,跳过第二个位置
undefined
;let [a, b, c] = [1, 2] // c=undefined
let [a, [b, c], d] = [1, [2]] // c=d=undefined
let [a, ...rest] = [1, 2, 3, 4] // rest = [2, 3, 4]
let [a, , ...rest] = [1, 2, 3, 4] // rest = [3, 4]
let [a, [b, ...rest], c] = [1, [2, ], 3, 4] // rest = []
let [a=1] = [] // a=1
let [a=1] = [undefined] // a=1
let [a=1] = [null] // a=null
let [x, y=x, z=2*x] = [1] // y=1,z=2
let [x, y=x] = [1, 10] // y=10
let [x=y, y] = [1, 10] // 这种写法易错、且没有太多意义,因为匹配是从左到右的
[b, a] = [a, b]
;Map
、Set
、String
等)都可以通过数组模式进行解构赋值;let [a, b] = new Map([
[1, 2], // a=[1,2]
[3, 4], // b=[3,4]
]);
function* gen() {
yield* [1, 2, 3]
}
let [x, y, z] = gen() // x=1,y=2,z=3
function firstPlusThird([first, ,third]) { return first + third; }
firstPlusThird([1, 2, 10, 20]) // 11
let [a, ...rest, b] = [1, 2, 3, 4] // 报错,剩余参数rest不能在中间
let [a=console.log(1)] = [1] // a=1且不会执行console.log(1)
let [a=console.log(1)] = [] // a=undefined且执行console.log(1)
let [x=y,y] = [] // 报错,y没有匹配到就赋值给x,x、y都没有声明成功
let [x, y] = 1 // 报错
let [x] = null // 报错
解构对象的属性,给相同属性名的变量进行赋值;和数组模式不同的是属性没有次序,要根据属性名赋值。
undefined
);const employee = {
id: 42,
isAdmin: true,
salary: '1.8w',
};
let { id, isAdmin } = employee; // id=42,isAdmin=true
let { isAdmin, id } = employee; // id=42,isAdmin=true
let { wage } = employee; // wage=undefined
/*
* : 后的才是变量名
* : 前的是要匹配的属性名
*/
let { id:ID } = employee; // ID=42,没有id这个变量
let { salary:wage } = employee; // wage='1.8w'
const employee2 = { }
let { id=1 } = employee; // id=42,匹配成功了
let { id=1 } = employee2; // id=1,匹配失败了
let { id:ID=1 } = employee; // ID=42,匹配成功了
let { id:ID=1 } = employee2; // ID=1,匹配失败了
const o = {
done: false,
materials: [ ['copper',], { obsidian: '3kg', granite: '10t' } ],
rate: '0%',
plus() { this.rate = 1 + +this.rate.slice(0, -1) + '%' }
}
let { materials: m } = o; // m=[ ['copper',], { obsidian: '3kg', granite: '10t' } ]
let { materials: [a, b] } = o; // a=['copper'],b={ obsidian: '3kg', granite: '10t' }
let { materials: [, { obsidian }] } // obsidian='3kg'
let employee3 = {
id: 12,
isAdmin: true
};
let x = 'id'
let { [x]: theId } = employee3 // theId=12
length
、0/1/…等索引),甚至原型链上的方法都可以赋值(尽管不能正常使用);Math
、Date
等一些好用的方法,可以独立使用的方法,都可以通过解构赋值的语法赋值给变量,使得调用更方便;let { 0:firstPos, 1:secondPos, length:len, at } = [1, 2, 3, 4]
firstPos // 1
secondPos // 2
len // 4
at(0) // 报错,因为没有指向的对象,脱离了数组
let { max, sin, PI:pi } = Math
max(1, 4, 2)// 4
sin(pi/2) // 1
let user = { id: 32,name: 'Li Ming' }, user2 = {};
function getUserId({ id }) {
return id;
}
getUserId(user) // 32
getUserId(user2) // undefined
:
前的是属性名,不是建立的变量,也不会建立;{}
可以没有变量;null
、undefined
不能解构的数据类型;()
包围。先声明后赋值模式的语句 + ()
。let { x:y } = { x: 1 } // 将属性x 的值赋值给y,创建了变量y,没有创建变量x
let { a: 1 } = null // 报错
let { } = null // 报错
let { a: 1 } = undefined // 报错
let { } = undefined // 报错
let m;
{ m } = { m: 'M' } // 报错
({ m } = { m: 'M' }) // m=1
({} = { a: 1, b: 2 }) // 这样是允许的,尽管很怪
字符串既可以作为类数组,进行数组模式的解构赋值;也可以作为对象,进行对象的解构赋值。
let str = 'Hello';
let strArr;
/* 作为数组被解构 */
let [a, b, , ,c] = str; // a='H',b='e',c='o'
/* 作为对象被解构 */
let { length:n, 0:firstChar } // n=5,firstChar='H'
({ 0:strArr[0], [str.length-1]:strArr[1] } = str)
strArr // ['H', 'o']
上面数组和对象的解构赋值,扩展部分提到过。在参数列表中做解构的类型一般就是数组和对象模式:
undefined
。let arr = [1, 2, 10, 20], obj = { value: 100 };
function getM([a, ,b], { value }) {
return a + b > value ? a + b: value; // 取大
}
getM(arr, obj) // 100
function f() { return [1, 2, 3] }
let [a, b, c] = f(); // a=1,b=2,c=3