ES6 允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构( Destructuring )。
一、数组的解构赋值
一个最简单的例子:
var [a,b,c] = [1,2,3];// a=1, b=2, c=3
这其实是一种模式匹配,只要两边的模式相同,就能正确地赋值:
let [a,[b,c]] = [1,[2,3]];// a=1, b=2, c=3
let [ , ,c] = [1,2,3];// c=3
let [c] = [1,2,3];// c = 1
let [a,c] = [1];// a = 1, c undefined
如果等号的右边不是数组(或者严格地说,不是可遍历的结构),那么将会报错
// 报错 let [foo] = 1; let [foo] = false; let [foo] = NaN; let [foo] = undefined; let [foo] = null; let [foo] = {};
默认值可以引用解构赋值的其他变量,但该变量必须已经声明:
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
二、对象的解构赋值
对象的解构与数组有一个重要的不同。数组的元素是按次序排列的,变量的取值由它的位置决定;而对象的属性没有次序,变
量必须与属性同名,才能取到正确的值:
let {first,second} = {first:1,second:2}; let {third,fourth} = {fourth:4,third:3}; console.log(first,second,third,fourth);// 1,2,3,4
如果变量名与属性名不一致,则:
let {first:number} = {first:1}; console.log(number); // 1 console.log(first); // Uncaught ReferenceError
let number = { first: 1, second: 2 } let {first,second} = number; //first = 1, second = 2
var node = { loc: { start: { line: 1, column: 5 } } }; var { loc: { start: { line }} } = node; line // 1 loc // error: loc is undefined start // error: start is undefined
对象的解构也可以指定默认值(默认值生效的条件是,对象的属性值严格等于 undefined ):
var {x = 3} = {}; x // 3 var {x, y = 5} = {x: 1}; x // 1 y // 5 var { message: msg = "biubiubiu" } = {}; msg // "biubiubiu"
三、字符串的解构赋值
字符串被转换成了一个类似数组的对象。
let [a,b,c] = 'abc'; console.log(a,b,c);// a=a,b=b,c=c let {length:len} = 'byebye'; console.log(len);// 6
四、数值和布尔值的解构赋值
如果等号右边是数值和布尔值,则会先转为对象。
let {toString: s} = 123; s === Number.prototype.toString // true let {toString: s} = true; s === Boolean.prototype.toString // true
五、函数参数的解构赋值
函数 add 的参数表面上是一个数组,但在传入参数的那一刻,数组参数就被解构成变量 x 和 y 。对于函数内部的代码来说,它们能感受到的参数就是 x 和 y
function add([x, y]){ return x + y; } add([1, 2]); // 3
函数参数的解构也可以使用默认值。
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]