在编码中,我们经常定义数组和对象,然后有组织的从中提取相关信息。ES6中添加的新特性解构可以简化这类任务。
对象解构
在es5及早期版本中,为了从对象中获取特定的数据并赋值给变量,编写了许多看起来类似的代码:
let origin = {
type: 'origin',
name: 'opt'
}
let type = origin.type,
name = origin.name;
console.log(type, name);//origin opt
如果用此方式,当有很多变量需要提取时,则显得十分麻烦。如果使用es6中的解构,将会简便很多。
对象的解构是在一个赋值操作符左边放置一个对象字面量。对象字面量里的变量必须与属性同名,才能取到正确的值。
let nowO = {
type: 'nowway',
name: 'nowO'
}
let { type, name } = nowO;
console.log(type, name); //nowway nowO
let { baz, foo } = { foo: "aaa", bar: "bbb" };
console.log(baz , foo); // undefined aaa
如果变量名与属性名不一致,必须写成下面这样:
//为非同名局部变量赋值
let nowO = {
type: 'nowway',
name: 'nowO'
};
let { type: curType, name: curName } = nowO;
//读取type属性并将其值存储在变量localType中
console.log(curType, curName);//nowway nowO
上面代码中,type和name是匹配的模式,curType和curName才是变量。真正被赋值的是变量curType以及curName,而不是模式type、name。
在进行解构赋值时,也可以为变量指定默认值。但是只有在指定的变量名作为属性名在对象中不存在或者该属性值严格等于undefined时,默认值才生效。
//默认值
let fruit = {
name: 'banana',
price: undefined
}
const { name, color = 'yellow', price = 3 } = fruit;
console.log(color, price);//yellow 3
如果想要在定义变量之后再使用解构的方式修改它们的值,需要使用小括号()将解构赋值语句包裹起来。因为添加括号后可以将块语句转化为一个表达式,从而实现解构赋值。
let fruit = {
name: 'banana',
price: 10
},
price = 13,
name = 'orange';
({ name, color = 'yellow', price } = fruit);
console.log(color, price);//yellow 3
解构也可以用于嵌套结构的对象
//嵌套对象解构
let nowO = {
type: 'nowway',
name: 'nowO',
loc: {
start: {
line: 1,
column: 2
},
end: {
line: 3,
column: 4
}
}
};
//在解构模式中使用了花括号{},表示在找到loc属性后,应当深入一层继续查找
let { loc: { end: { line }, start: startPos } } = nowO;
console.log(line);//3
console.log(startPos.line, startPos.column);//1 2
startPos.hh = '43';
console.log(nowO.loc.start);//{line: 1, column: 2, hh: "43"}
在解构模式中使用了花括号{},表示匹配到某属性后,应该深入一层继续匹配。
数组解构
与对象解构相比,数组解构就简单很多。在数组的解构语法中,通过值在数组中的位置进行选取,且可以将其存储在任意变量中,未显示声明的元素会直接被忽略。在这个过程中,数组本身不发生变化。
//数组解构
let colors = ["red", "yellow", "green"];
let [firstColor, secondColor] = colors;
console.log(firstColor, secondColor);//red yellow
let [, , thirdColor] = colors;
console.log(thirdColor);//green
数组解构也可以用于赋值上下文,但不需要用小括号包裹。
let colors = ["red", "yellow", "green"];
let red = "deepRed",
yellow = "deepYellow";
[red, yellow] = colors;
console.log(red, yellow); //red yellow
可以在数组解构赋值表达式中为数组中的任意位置添加默认值,当指定位置的数组成员不存在或者严格等于undefined时,默认值才生效。
//默认值
let animals = ["dog", null];
let [dog, panda = "panda", cat = "cat"] = animals;
console.log(dog, panda, cat);//dog null cat
上面这个例子中,由于null不严格等于undefined,所以panda不会取默认值;同时由于位置2不存在成员值,所以cat需要使用默认值。
嵌套数组解构与嵌套对象解构类似,在原有的数组模式中插入另一个数组模式,即可将解构过程深入到下一层级。
let colors = ["red", ["green", "blue"]];
let [firstColor, second] = colors;
console.log(firstColor, second); //red ["green", "blue"]
let [, [secondColor]] = colors;
console.log(secondColor);//green
second.push("YELLOW");
console.log(colors[1]);//["green", "blue", "YELLOW"]
在es6的函数中可以存在不定参数,在数组解构语法中有类似的概念——不定元素。也是需要通过…语法,它将数组中的其余元素赋给一个特定的变量。
let colors = ["red", ["green", "blue"]];
let [red, ...myColors] = colors;
console.log(myColors[0]);//["green", "blue"]
myColors[0].push("yellow");
console.log(colors[1]);//["green", "blue", "yellow"]
利用数组解构还可以进行交换变量值。而且这种方式十分方便。
//交换变量值
let a = 10, b = 20;
[a, b] = [b, a];
console.log(a, b);//20 10
函数参数的解构赋值
函数的参数也可以使用解构赋值。
function count([a, b]) {
return a * b;
}
console.log(count([2, 3]));//6
上面代码中,函数count的参数表面上是一个数组,但在传入参数的那一刻,数组参数就被解构成变量a和b。
let arr = [[1, 2], [3, 4]].map(([a, b]) => a + b);
console.log(arr);//[3, 7]
解构参数也可以存在默认值。
function setValues(city, season,
{
days = 10,
thing
} = { thing: 'travel' }) {
return {
city,
season,
days,
thing
}
}
console.log(setValues('Thailand', 'fall'));
// { city: "Thailand", season: "fall", days: 10, thing: "travel" }
字符串的解构赋值
字符串也可以解构赋值。这是因为此时,字符串被转换成了一个类似数组的对象。
const [a, b, c] = 'nihao';
console.log(a, b, c);//n i h
const { length: len } = 'hello'; //字符串有length属性
console.log(len);//5
数值和布尔值的解构赋值
解构赋值时,如果等号右边是数值和布尔值,则会先转为对象。
const { toString: numStr } = 5.8;
console.log(numStr === Number.prototype.toString);//true
const { toString: boolStr } = true;
console.log(boolStr === Boolean.prototype.toString);//true