愿你坚持不懈,努力进步,进阶成自己理想的人

—— 2017.09, 写给3年后的自己

《ECMAScript6入门》学习笔记之解构

ES6中引入了解构的特性,允许我们以一种更简短的方式来实现数组、对象成员赋值给各种变量

一、传统场景

我们想要提取数组中的元素到不同的变量中,传统做法如下:

var arr = ['A', 'B', 'C'];
var a = arr[0]; // 'A'
var b = arr[1]; // 'B'
var c = arr[2]; // 'C'

但是使用解构语法,只需要这么写:

var [a, b, c] = arr;
console.log(a, b, c); // 'A' 'B' 'C'

那么接下来,来详细了解下解构语法的用法吧


二、数组解构

数组的解构,只需要左边构造类似于右边的形式,就能提取出右边的值,如:

var [a, b] = ['Hello', 'world'];
// 得到a的值为'Hello',b的值为'World'

对于嵌套的案例,这条规则仍然适用:

var [a, [[[b]]]] = ['Hello', [[['World']]]];

我们在解构体前面可以加入varconstlet,如此一来,将会在解构的同时声明变量、常量,如果不加入这些关键字,那么实现的则是赋值
问:如何只提取部分元素?
有时候,我们可能并不需要提取全部的元素,而是想提取部分元素,那么这种情况下,我们可以使用如下的形式:

var [,,c] = ['A', 'B', 'C'];
// 得到c的值为'C'

此外,还有以下的这种提取形式:

var [head, ...tail] = [1, 2, 3, 4, 5];
// 得到 head 的值为 1,tail的值为[2, 3, 4, 5]

当我们访问空的数组或者越界的索引时,对其解构,行为和对数组索引的行为一致,得到的都是undefined,如:

var [a] = [];
// a的值为undefiend

此外,我们还可以结合generator来使用解构,如:

function* gen () {
    for (let i=0; i<5; ++i) {
        yield i;
    }
}

var [a, b, c, ...d] = gen();
/*
得到的结果:
a -> 0
b -> 1
c -> 2
d -> [3, 4]
*/

我们还可以指定当数组的某一个成员不存在时的默认值,如:

var [a = 5] = [];
// 得到a的值为5 


三、对象解构

对象的解构,核心也是构造一个左边的模式,来匹配右边的模式,如:

var { name: _name, age: _age } = {
    name: 'RuphiLau',
    age : 21
}
// 得到的结果为:_name -> 'RuphiLau',_age -> 21

当解构体的keyvalue名称一样时,可以简写,即:

var { name: name, age: age } = { name: 'RuphiLau', age: 21 }
// 可以简写为:
var { name, age } = { name: 'RuphiLau', age: 21 }

可以进行嵌套解构,如:

var obj = {
    catalogName: '电影',
    list: [
        '加勒比海盗',
        '变形金刚'
    ],
    info: [
        {score: 9.0}
    ]
};
var {catalogName, list: [ ...movies ], info: [{score}]} = obj;
/*
可以得到:
catalogName -> '电影'
movies -> ["加勒比海盗", "变形金刚"]
score -> 9.0
*/

解构对象的时候,如果不同时赋值,那么像以下这种写法会报错:

{ a, b } = { a: 1, b: 2 };

这是因为以{开头的,会被JavaScript引擎认为是块语句,从而产生二义性问题。要解决这个问题,可以使用一对圆括号包裹,如:

({a, b} = { a: 1, b: 2})

对象中的解构,也可以有默认值,用于对未定义值取默认值,如:

var { a = 1 } = {};
// a的值为1
var { error: code = 500 } = {};
// code的值为500


四、解构的应用

解构语法有着很广泛的应用,使用解构可以使得我们写出更简短易读的代码,以下总结几种常用的应用

1、函数参数中应用

我们可能希望有这样子的函数API:不需要记住它的参数顺序,只需要传入一个名称,它就会自动匹配,使用解构便可以达到这种效果,如下:

function ajax({
    url,
    method,
    cbOnload,
    cbOnerror
}) {
    console.log('配置信息为:');
    console.log(url, method, cbOnload, cbOnerror);
}

使用时候,就可以如:

ajax({url: '//ruphi.cn'});
ajax({method: 'GET', url: '//ruphi.cn'});
// 等等

如此一来,我们便能够更加语义化地调用一个函数。
此外,在传统情况下,JavaScript中是不能定义参数默认值的,而我们一般使用以下的形式来定义一个参数的默认值,如:

function toast(message, delay) {
    delay = delay || 1000;
    // ...
}

使用了解构语法,我们就无需再这么做了,只需要如:

function toast({
    message,
    delay = 1000
}) {
    // ...
}

2、多重返回值

可以使用解构来得到一个函数的多重返回值,如:

function multiResult () {
    return [1, 2, 3];
}
// 传统情况下:
var res = multiResult();
var a = res[0]; // 1
var b = res[1]; // 2
var c = res[2]; // 3

// 使用解构:
[a, b, c] = multiResult();

3、导入部分CommonJS模块

可以使用解构的形式,来导入部分CommonJS模块,如:

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