ES6学习笔记-解构-Destructuring

Author Avatar
Splendour 12月 13, 2015

什么是解构

我们以访问数组中的前三个元素为例

传统的访问方式

let frist = array[0];
let second = array[1];
let third = array[2];

使用解构的特性

let [first, second, third] = array;

两段代码是完全等效的,利用新特性能使代码更加简洁和易读

数组与迭代器的解构

一般形式

let [variable1, variable2, ..., variableN] = array;

嵌套数组的解构

let [a, [[b], c]] = [1, [[2], 3]];
console.log(a);   //1
console.log(b);   //2
console.log(c);   //3

留空跳过元素

let [,,c] = [1, 2, 3];
console.log(c);   //3

结合不定参数

let [head, ...tail] = [1, 2, 3, 4];
console.log(tail);    //[2, 3, 4]

越界时的结果

let [missing] = [];
console.log(missing);   //undefined

在迭代器中的使用

function* fibs() {
  let a = 0;
  let b = 1;
  while (true) {
    yield a;
    [a, b] = [b, a + b];
  }
}
let [first, second, third, forth, fifth, sixth] = fibs();
console.log(sixth);   //5

对象的解构

一般形式

let { name: nameA } = { name: 'Lily' };
let { name: nameB } = { name: 'Lucy' };
console.log(nameA);   //Lily
console.log(nameB);   //Lucy

属性名与变量名一致时的简写

let { foo, bar } = { foo: 'foo', bar: 'bar' }
console.log(foo);   //'foo'
console.log(bar);   //'bar'

嵌套对象解构

let complicatedObj = {
  arrayProp: [
    'Zapp',
    { second: 'Brannigan' }
  ]
}
let {
  arrayProp: [
    first,
    { second }
  ]
} = complicatedObj;
console.log(first);   //'Zapp'
console.log(second);   //'Brannigan'

解构未定义的属性

let { missing } = {};
console.log(missing);   //undefined

若变量已定义好,解构语句中不存在 let 等关键字

{ a } = { a: 10 };    //Syntax error 语法错误
(){ a } = { a: 10 });   //无语法错误

解构值不是对象、数组或迭代器

尝试解构 undefined 或者 null 时,会得到类型错误

let { blowUp } = null;  //TypeError: null has no properties

然而,解构其他原始类型就不会报错,但是会得到 undefined

let { wtf } = NaN;
console.log(wtf);   //undefined

原因:当使用对象赋值模式时,被解构的值会被强制转换为对象,null 和 undefined 无法进行转换所以出现错误。

默认值

let [missing = true] = [];
console.log(missing);   //true

实际应用

函数参数定义

作为开发者,我们需要实现设计良好的API,通常的做法是为函数为函数设计一个对象作为参数,然后将不同的实际参数作为对象属性,以避免让API使用者记住 多个参数的使用顺序。我们可以使用解构特性来避免这种问题,当我们想要引用它的其中一个属性时,大可不必反复使用这种单一参数对象。

function removeBreakpoint({ url, line, column }) {
  // ...
}

配置对象参数

当我们构造一个提供配置的对象,并且需要这个对象的属性携带默认值时,解构特性就派上用场了。举个例子,jQuery的ajax函数使用一个配置对象作为它的第二参数,我们可以这样重写函数定义:

jQuery.ajax = function (url, {
  async = true,
  beforeSend = noop,
  cache = true,
  complete = noop,
  crossDomain = false,
  global = true,
  // ... 更多配置
}) {
  // ... do stuff
};

如此一来,我们可以避免对配置对象的每个属性都重复var foo = config.foo || theDefaultFoo;这样的操作。

与迭代器协同使用

在迭代 Maps 时,可以得到一些列形如[key, value]的键值对,此时利用解构可以更轻松地访问键和值

let map = new Map();
map.set(window, 'the global');
map.set(document, 'the document');
for (let [key, value] of map) {
  console.log(`${key} is ${valuel}`);
}

只遍历键

for (let [key] of map) {
  //...
}

或只遍历值

for (let [, value] of map) {
  //...
}

多重返回值

  • 返回一个数组将结果解构
    function returnMultipleValues() {
    return [1, 2];
    }
    let [first, second] = returnMultipleValues();
    
  • 用一个对象作为容器并为返回值命名
    function returnMultipleValues() {
    return {
      first: 1,
      second: 2
    }
    }
    let { first, second } = returnMultipleValues();
    

导入模块

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