【ES6】解构

解构的本质是模式匹配,只要等号左右两边的模式相同,左边的变量就会被赋予对应的值
解构ES5实现:

1
2
3
4
'use strict';
var obj={ foo: "aaa", bar: "bbb"};
var bar=obj.foo;
var foo=obj.bar;

脑图结构http://naotu.baidu.com/file/9e48bcf4bbd766715f3c64d5cc790174?token=313fa87a66f621d0

[TOC]

解构

  • 模式:变量其中模式是原来对象中存在的属性名,变量是要赋值的新变量名,如果模式和新的变量名一样有则省略变量名
  • 限定范围:只要某种数据结构具有 Iterator 接口,都可以采用数组形式的解构赋值,
  • 解构赋值的规则是,只要等号右边的值不是对象或数组,就先将其转为对象。由于undefined和null无法转为对象,所以对它们进行解构赋值,都会报错。

    1、数组解构

    可以用数组下标作为模式 [a, b, c] = [1, 2, 3] ; let {0:first2,[arr.length-1]:last}=arr;

2、对象解构

1
let { foo, bar } = { foo: "aaa", bar: "bbb" };

如果要另起变量名:

1
let { foo: baz } = { foo: 'aaa', bar: 'bbb' };

将解构的值放入数组:

1
2
3
4
let obj = {};
let arr = [];
({ foo: obj.prop, bar: arr[0] } = { foo: 123, bar: true });

3、字符串解构

字符串被转换成一个类似数组的对象

1
2
const [a,b,c,d,e]="hello"
//a是h,b是e,c是l,d是l,e是o

4、函数参数解构

(1)参数是数组时

在传入参数的那一刻,数组参数就被解构成变量x和y。对于函数内部的代码来说,它们能感受到的参数就是x和y

1
2
3
4
function add([x, y]){
return x + y;
}
add([1, 2]); // 3

(2)参数是对象时

1
2
3
4
5
6
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]

5、数值和Boolen的解构

解构时如果等号右边时数值和对象,则会先转换成对象


解构默认值

默认值在被解构的对象的值是undefined时才生效
如果一个成员不严格等于undefined,默认值是不会生效的,比如被解构对象的值是null,则默认值是不会生效的

数组解构默认值

1
2
3
4
let [foo = true] = [];
foo // true
let [x, y = 'b'] = ['a']; // x='a', y='b'
let [x, y = 'b'] = ['a', undefined]; // x='a', y='b'

对象解构默认值

1
2
3
var {x, y = 5} = {x: 1};
x // 1
y // 5

函数解构默认值

(1)给解构每个变量赋默认值
一个个参数独立生效

1
2
3
4
5
6
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]

(2)给参数整体赋默认值
在整个参数对象没有赋值的时候才生效

1
2
3
4
5
6
7
8
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(); // [0, 0] //生效


剩余项

1
2
let colors = ["red", "green", "blue"];
let [firstC, ...restC] = colors;//restC是数组["green", "blue"]

使用剩余项进行克隆:

1
2
3
let colors = ["red", "green", "blue"];
let [...restC] = colors;
console.log(restC);//["red", "green","blue"]


普通解构与嵌套解构

1
2
3
4
5
6
7
8
9
/* 普通解构*/
let {name,age}=obj;
console.log(name+age);
/* 嵌套解构*/
let {name,sex,skill:{eat,frontend}}=obj;//这里的skill是模式
console.log(name+' '+eat+' '+frontend)
let {skill:skills}=obj;
console.log(skills)

圆括号问题

只有一种情况可以使用圆括号

可以使用圆括号的情况只有一种:赋值语句的非模式部分,可以使用圆括号。

要点:

  • 也就是说新变量是已经声明过了的
  • 非模式部分
    1
    2
    3
    [(b)] = [3]; // 正确
    ({ p: (d) } = {}); // 正确
    [(parseInt.prop)] = [3]; // 正确

绝对不能使用圆括号情况

1、变量声明语句中

1
let [(b)]=[1,2,3];//报错

2、函数参数

1
function f([z,(x)]) { return x; }//报错

3、赋值语句的模式
赋值语句的模式不能被包裹在圆括号中

1
[({ p: a }), { x: c }] = [{}, {}];//p和x被包裹在圆括号中,报错


用途

1、交换变量的值
2、从函数返回多个值(感觉这个有点牵强,这不就是解构的基本用法吗,和函数没有啥重要关系吧)
3、函数参数的定义:可以方便地将一组参数和变量名对应起来
4、提取JSON数据:就是对象解构
5、指定函数参数默认值
6、遍历Map结构:配合变量的解构赋值,获取键名和键值就非常方便

1
2
3
4
5
6
7
8
9
10
11
12
13
14
const map = new Map();
map.set('first', 'hello');
map.set('second', 'world');
for (let [key, value] of map) {
console.log(key + " is " + value);
}
// 获取键名
for (let [key] of map) {
// ...
}
// 获取键值
for (let [,value] of map) {
// ...
}

7、指定输入模块的具体方法:加载模块时,往往需要指定输入哪些方法。解构赋值使得输入语句非常清晰

1
const { SourceMapConsumer, SourceNode } = require("source-map");


【持续更新中…】
注:大部分摘自阮一峰ES6入门,对此作高度总结分类,便于记忆

热评文章