ES6 解构

解构

ES6 新增了解构( destructuring ),它按照一定模式,从数组和对象中提取值,对变量进行赋值,这是将一个数据结构分解为更小的部分的过程。

对象解构

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

let { bar, foo } = { foo: "aaa", bar: "bbb" };
foo // "aaa"
bar // "bbb"
默认值

当你使用解构赋值语句时,如果所指定的本地变量在对象中没有找到同名属性,那么该变量会被赋值为 undefined 。

let node = {
        type: "Identifier",
        name: "foo"
    };
let { type, name, value } = node;
console.log(type);    // "Identifier"
console.log(name);    // "foo"
console.log(value);    // undefined

你可以选择性地定义一个默认值,以便在指定属性不存在时使用该值。若要这么做,需要在属性名后面添加一个等号并指定默认值。

let node = {
        type: "Identifier",
        name: "foo"
    };
let { type, name, value = true } = node;
console.log(type);    // "Identifier"
console.log(name);    // "foo"
console.log(value);    // true
赋值给不同的本地变量名
let node = {
        type: "Identifier",
        name: "foo"
    };
let { type: localType, name: localName } = node;
console.log(localType);     // "Identifier"
console.log(localName);     // "foo"

type: localType 这种语法表示要读取名为 type 的属性,并把它的 值存储在变量 localType 上。该语法实际上与传统对象字面量语法相反,传统语法将名称放在冒号左边、值放在冒号右边;而在本例中,则是名称在右边,需要进行值读取的位置则被放在了左边。

数组解构

数组解构的语法看起来与对象解构非常相似,只是将对象字面量替换成了数组字面量。数组解构时,解构作用在数组内部的位置上,而不是作用在对象的具名属性上。

let [foo, [[bar], baz]] = [1, [[2], 3]];
foo // 1
bar // 2
baz // 3

let [ , , third] = ["foo", "bar", "baz"];
third // "baz"

let [x, , y] = [1, 2, 3];
x // 1
y // 3

只要等号两边的模式相同,左边的变量就会被赋予对应的值

剩余项

使用 ... 语法来将剩余的项目赋值给一个指定的变量

let [head, ...tail] = [1, 2, 3, 4];
head // 1
tail // [2, 3, 4]

let [x, y, ...z] = ['a'];
x // "a"
y // undefined
z // []

let colors = ["red", "green", "blue"];
let [...clonedColors] = colors;
clonedColors   // ["red", "green", "blue"]

剩余项必须是数组解构模式中最后的部分,之后不能再有逗号,否则就是语法错误。

混合解构

对象与数组解构能被用在一起,以创建更复杂的解构表达式。在对象与数组混合而成的结构中,这么做便能准确提取其中你想要的信息片段。

let node = {
        type: "Identifier",
        name: "foo",
        loc: {
            start: {
                line: 1,
                column: 1 
            },
            end: {
                line: 1,
                column: 4 
            }
        },
        range: [0, 3]
    };
let {
    loc: { start },
    range: [ startIndex ]
} = node;
console.log(start.line);       // 1 
console.log(start.column);     // 1 
console.log(startIndex);       // 0

字符串解构

字符串也可以解构赋值。这是因为此时,字符串被转换成了一个类似数组的对象。

const [a, b, c, d, e] = 'hello';
a // "h"
b // "e"
c // "l"
d // "l"
e // "o"

类似数组的对象都有一个length属性,因此还可以对这个属性解构赋值。

let {length : len} = 'hello';
len // 5

参数解构

当 JS 的函数接收大量可选参数时,一 个常用模式是创建一个 options 对象,其中包含了附加的参数。

// options 上的属性表示附加参数
function setCookie(name, value, options) {
    options = options || {};
    let secure = options.secure,
        path = options.path,
        domain = options.domain,
        expires = options.expires;
// 设置 cookie 的代码
}
// 第三个参数映射到 options
setCookie("type", "js", {
    secure: true,
    expires: 60000
});

很多 JS 的库都包含了类似于此例的 setCookie() 函数。在此函数内, name 与 value 参 数是必需的,而 secure 、 path 、 domain 与 expires 则不是。此处虽然无须列出一堆额外的具名参数。但无法仅通过查看函数定义就判断出函数所期望的输入。参数解构能够更清楚地标明函数期望输入。它使用对象或数组解构的模式替代了具名参数。

function setCookie(name, value, { secure, path, domain, expires }) { // 设置 cookie 的代码
}
setCookie("type", "js", {
    secure: true,
    expires: 60000
});

解构参数在没有传递值的情况下类似于常规参数,它们会被设为 undefined 。同样参数解构也可以设置默认值。

用途

互换两个变量的值
let a = 1, b = 2;
[a, b] = [b, a ];
console.log(a);     // 2
console.log(b);     // 1

简洁,易读,语义清晰。

从函数返回多个值
// 返回一个数组

function example() {
  return [1, 2, 3];
}
let [a, b, c] = example();

// 返回一个对象

function example() {
  return {
    foo: 1,
    bar: 2
  };
}
let { foo, bar } = example();

如果函数要返回多个值,我们只能将它们放在数组或对象里返回。有了解构赋值,取出这些值就非常方便。

提取 JSON 数据
let jsonData = {
  id: 42,
  status: "OK",
  data: [867, 5309]
};

let { id, status, data: number } = jsonData;

console.log(id, status, number);
// 42, "OK", [867, 5309]
函数参数的定义
// 参数是一组有次序的值
function f([x, y, z]) { ... }
f([1, 2, 3]);

// 参数是一组无次序的值
function f({x, y, z}) { ... }
f({z: 3, y: 2, x: 1});

解构赋值可以方便地将一组参数与变量名对应起来。

推荐阅读更多精彩内容

  • 前面的话 我们经常定义许多对象和数组,然后有组织地从中提取相关的信息片段。在ES6中添加了可以简化这种任务的新特性...
    sunnyghx阅读 473评论 0 0
  • 参考:ES6入门(阮一峰)解构:解构与构造数据截然相反。 例如,它不是构造一个新的对象或数组,而是逐个拆分现有的对...
    IceLake阅读 1,536评论 0 1
  • 注意:iOS所有图标的圆角效果由系统生成,给到的图标本身不能是圆角的。 桌面图标 (app icon)for iP...
    独居焚香阅读 268评论 0 3
  • Mixed martial arts (MMA) is a full-contact combat sport t...
    怪物办公室阅读 120评论 0 0
  • 如果诊断的目的是为了治愈的话。 如果本身能够治愈为什么要冠上诊断后的标签久久不能抬头与治愈。
    朱周阅读 54评论 0 0