ES6变量的解构赋值本质上是“模式匹配”,只要等号两边的模式相同,左边的变量就会被赋予匹配的右边的值,如果匹配不成功变量的值就等于undefined
ES6中只要某种数据有Iterator接口(也就是可以循环迭代 Iterable对象),都可以进行数组的解构赋值
数组解构
(1)基本赋值
let [a,b,c] = [1,2,3];
console.log(a,b,c);
(2)先声明再赋值
let a,b,c;
[a,b,c] = [1,2,3];
console.log(a,b,c);
(3)不完全解构
let [a,,c,d] = [1,2,3];
console.log(a,c,d); //1 3 undefined
(4)默认参数
如果值为undefined,变量将取得默认参数
let [a=10,b=20,c=30,d=40] = [1,2,3];
console.log(a,b,c,d);//1 2 3 40
(5)剩余参数
let [a=10,...b] = [1,2,3];
console.log(a,b);//1 [2, 3]
(6)Iterable对象(Iterator接口) 会按数组处理
字符串:
let [a,b,c] = "123";
console.log(a,b,c);//1 2 3
Set对象
let set = new Set();
set.add(1).add(2).add(3);
let [a,b,c] = set;
console.log(a,b,c);//1 2 3
Map对象
let map = new Map();
map.set("a",1)
.set("b",2)
.set("c",3);
let [[x,m],[y,n],[z]] = map;
console.log(x,y,z,m,n); //a b c 1 2
Generator函数返回的对象
function* gen() {
yield "a";
yield "b";
yield "c";
}
let genObj = gen();
let [x,y,z] = genObj;
console.log(x,y,z); a b c
解构数组可以交换变量
let a = 1, b = 2;
[a, b] = [b, a];
console.log(a,b) //2 1
引发的思考:计算出数组每项的值,解构赋值时一一对应。下面示例中,[b=a, a=3] 数字第一项b=a,该值为1,第二项为3;所以解构赋值a为第一项的值,b为第二项的值
所以,思考下面例子
let a = 1, b = 2;
[a, b] = [b=a, a=3];
console.log(a,b) //1 3
对象解构
(1)基本赋值
var o = {p: 42, q: true};
var {p, q} = o;
console.log(p); // 42
console.log(q); // true
(2)先声明再赋值
var a, b;
({a, b} = {a: 1, b: 2});
注意:赋值语句周围的圆括号 ( ... )
在使用对象字面量无声明解构赋值时是必须的。
{a, b} = {a: 1, b: 2}
不是有效的独立语法,因为左边的 {a, b}
被认为是一个块而不是对象字面量。
然而,({a, b} = {a: 1, b: 2})
是有效的,正如 var {a, b} = {a: 1, b: 2}
你的 ( ... )
表达式之前需要有一个分号,否则它可能会被当成上一行中的函数执行。
(3)对象赋值左侧的属性名作为匹配模式,属性值作为变量
左侧属性名和变量名不同名
let {p:a, q:b} = {p:1, q:2};
console.log(a, b) //1 2
左侧属性名和变量同名
let {a, b} = {a:1, a:2};// let {a:a, b:b} = {a:1, a:2};
console.log(a, b) //1 2
(4)默认值
let {p:a=3, q:b=4} = {p:1, q:undefined};
console.log(a, b); //1 4
let {a=3, b=4} = {a:1, b:undefined};
console.log(a, b); //1 4
(5)剩余参数的提案已经到第四阶段,不推荐使用
(6)计算属性名
let key = "z";
let {[key]: a} = {z: 1};
console.log(key, a); //"z" 1
什么是计算属性?Object_initializer
let key = "z";
let {[key + "y"]: a} = {zy: 1};
console.log(key, a); //"z" 1
(7)无效的标识符作为属性名
标识符:字母、$、下划线开头,可以包含数字
const foo = { 'fizz-buzz': true };
const { 'fizz-buzz': fizzBuzz } = foo;
console.log(fizzBuzz); // "true"
(8)解构对象时会查找原型链
如果属性不在对象 自身,会向原型链 上查找
const protoObj = {
name: "protoObj"
}
const obj = Object.create(protoObj);
obj.a = 1;
obj.b = 2;
let {a, b, name} = obj;
console.log(a,b,name); //1 2 "protoObj"
(9)从 函数实参中提取数据
函数接收对象作为参数, 可以通过该对象的解构,提取数据
function userId({id}) {
return id;
}
function whois({displayName, fullName: {firstName: name}}){
console.log(displayName + " is " + name);
}
var user = {
id: 42,
displayName: "jdoe",
fullName: {
firstName: "John",
lastName: "Doe"
}
};
console.log("userId: " + userId(user)); // "userId: 42"
whois(user); // "jdoe is John"
采用的思路是:函数的形参作为解构对象的左侧内容,函数的实参作为解构对象的右侧具体对象,通过匹配关系进行解构,得到需要的值。
原始值的解构
数字、布尔值和字符串,根据包装类的特性,通过对象解构;同时,ES6特性中,字符串可以解构为数组。
let {toString: toStr} = 123;
console.log(toStr === Number.prototype.toString) //true
let {toString: toS} = true;
console.log(toS === Boolean.prototype.toString) //true
let {length: len} = "xyz";
console.log(len); //3
let [a, b, c] = "xyz";
console.log(a,b,c); // x y z
for of迭代和解构
该实例的实现,是对解构赋值的灵活应用,不管以任何形式得到的数据(对象或数组),都可以通过解构赋值,得到对应的值
var people = [
{
name: 'Mike Smith',
family: {
mother: 'Jane Smith',
father: 'Harry Smith',
sister: 'Samantha Smith'
},
age: 35
},
{
name: 'Tom Jones',
family: {
mother: 'Norah Jones',
father: 'Richard Jones',
brother: 'Howard Jones'
},
age: 25
}
];
for (var {name: n, family: {father: f}} of people) {
console.log('Name: ' + n + ', Father: ' + f);
}
// "Name: Mike Smith, Father: Harry Smith"
// "Name: Tom Jones, Father: Richard Jones"
实例:解构嵌套对象数组
const metadata = {
title: 'Scratchpad',
translations: [
{
locale: 'de',
localization_tags: [],
last_edit: '2014-04-14T08:43:37',
url: '/de/docs/Tools/Scratchpad',
title: 'JavaScript-Umgebung'
}
],
url: '/en-US/docs/Tools/Scratchpad'
};
let {
title: englishTitle, // rename
translations: [
{
title: localeTitle, // rename
},
],
} = metadata;
console.log(englishTitle); // "Scratchpad"
console.log(localeTitle); // "JavaScript-Umgebung"
思考
数组和对象的解构引发的思考:
数组是有序列表,通过左边的index索引值找到对应的变量,通过右边的index索引值找到对应的值,然后进行匹配赋值。
而对象,通过左边的属性名找到对应的属性值变量,通过右边的属性名找到对应的属性值,然后进行匹配赋值。