解构赋值

导读:解构?赋值?带你了解 ES6/7/8/9+ 的新特性。

本文包含了如下知识点:

  • 数组解构
  • 顺序解构
  • 剩余参数解构
  • 对象解构
  • 键名解构
  • 别名解构
  • 层级解构
  • 剩余属性解构
  • 默认赋值
  • 基本类型解构
  • 数字类型解构
  • 字符串类型解构
  • undefined | null 特殊类型解构
  • 实际应用
  • for ... of 循环解构
  • 函数参数解构
  • 交换变量
  • ES6 的 import 语句
  • 注意事项
  • 已定义变量的解构赋值

定义

解构赋值(Destructuring Assignment)是 ES6 中新提出的一种表达式,通过解构赋值,可以将属性或值从对象/数组中取出,直接赋予变量。

数组解构

顺序解构

按照数组顺序一一赋值。

看一个最简单的例子:

const array = [1, 2, 3, 4];

const [a, b] = array;
a === array[0]; // a === 1
b === array[1]; // b === 2

这是一个最基本的数据解构赋值,即按照对应的顺序将数组中的值分配给对应的变量。

小技巧:解构字符串

字符串也可以被解构,如:

const text = 'Hello, world!';

const [h, e, l, ...rest] = text;
h === 'H';
e === 'e';
l === 'l';
rest => [ 'l', 'o', ',', ' ', 'w', 'o', 'r', 'l', 'd', '!' ]

小技巧:跳跃解构

可以使用空变量来跳过某些不需要的值:

const array = ['not this', 'get this'];

const [, text] = array; // 不需要第一个变量

剩余参数解构

使用剩余参数语法获取数组的剩余元素。

看一个例子:

const array = [1, 2, 3, 4];

const [a, ...rest] = array;
a === array[0]; // a === 1
rest => [2, 3, 4];

默认赋值

数组解构支持设置默认值。
const array = [1, 2];

const [a, b, c = 100] = array;
a === array[0]; // a === 1
b === array[1]; // b === 2
c === 100;

对象解构

键名解构

按照对应的键名来解构对象。

看一个例子:

const object = { name: 'Ruby', alias: 'Oooops', age: 18 };

const { name, alias } = object;
name === object.name; // name === 'Ruby'
alias = object.alias; // alias === 'Oooops'

和数组的顺序解构大同小异,声明对应的键名即可。

小技巧:解构获取方法

const { log, sin, cos } = Math;

const { log, info } = console;

小技巧:数组的对象化解构

如快捷的获取首个或最后一个字符:

const array = ['first', 'some', 'other', 'last'];

const { 0: first, [array.length - 1]: last } = array;
first === 'first';
last === 'last';

别名解构

使用别名解构,可以为变量声明自己的名称,即 { 属性: 变量名 }

看一个例子:

const object = { name: 'Ruby', alias: 'Oooops', age: 18 };

const { name: who } = object;
who === object.name; // who === 'Ruby'

层级解构

解构对象中的对象或数组。

看一个例子:

const article = {
    author: {
        name: 'Lily',
        age: 18
    }
};

const { author: { name, age } } = article;

name === article.author.name; // name === 'Lily'
age === article.author.age; // age === 18

小技巧:对象与数组的层级解构

快速获取第一条评论:

const article = {
    comments: [
        { user: 'Allen', content: 'Hello, world!' },
        { user: 'anonymous', content: `I don't like it!` }
    ]
};

const { comments: [ first, ...rest ]} = article;
first => { user: 'Allen', content: 'Hello, world!' };
rest => [ { user: 'anonymous', content: "I don't like it!" } ];

剩余属性解构

使用剩余参数语法获取对象的剩余属性,并组合成一个新的对象。

看一个例子:

const object = { name: 'Ruby', alias: 'Oooops', age: 18 };

const { name, ...rest } = object;
name === object.name; // name === 'Ruby'
rest => { alias: 'Oooops', age: 18 };

剩余参数会获取到所有未赋值的属性,并生成一个新的对象。

默认赋值

对象的解构赋值也支持设置默认值。

如下所示:

const object = { };

const { age = 10 } = object;
age === 10;

小提示:对应属性必须为 undefined

默认值只有在对应属性为 undefined 时才会生效,null | 0 | '' 等均不会生效,如:

const object = { name: '', alias: null, age: 0 };

const { 
    name = 'anonymous', 
    alias = 'none', 
    age = 10, 
    sex = 'unknown' 
} = object;

name === '';
alias === null;
age === 0;
sex === 'unknown'; // 只有 undefined 才会使默认值生效

小技巧:别名默认值的奇妙写法

如果使用了别名解构,还要设置默认值,那应该怎么写呢?

const object = {};

const { alias: name = 'anonymous' } = object;

name === 'anonymous';

总觉得怪怪的,要是 TypeScript 该怎么写?

还真没法写。

基本类型解构

数字类型解构

解构前解释器会自动将其转换为对象。

看一段代码:

const num = 123.456;

const { toFixed } = num;
`${toFixed.call(num, 1)}` === '123.5'; // 注意,数值不相等,只是显示相同

字符串类型解构

同理,解释器也会自动将其转化为对象。
const text = 'text';

const { toString } = text;
toString.call(text) === 'text';

undefined | null 特殊类型解构

因为 undefined 以及 null 无法被转换为对象,因此无法解构。

实际应用

for of 循环解构

for ... of 循环中使用解构,快速获取对象属性:
const array = [{ name: 'Allen', age: 18 }];

for (const {name, age} of array) {
    name === 'Allen';
    age === 18;
}

函数参数解构

解构参数以快速获取内容。

解构数组

function add([x, y]) {
	return x + y;
}

add([1, 2]) === 3;

解构对象

function display({ name, age }) {
    return `${name} is ${age} years old.`;
}

const person = { name: 'Faker', age: 24 };

display(person) === 'Faker is 24 years old.';

参数默认值

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

add() === 3;

function sub({ minus, minute } = { minus: 10, minute: 5 }) {
    return minus - minute;
}

sub() === 5;

交换变量

剩去中间人,快速交换变量。

交换 a 和 b 的值:

let a = 10;
let b = 20;

[a, b] = [b, a];
a === 20;
b === 10;

ES6 的 import 语句

想不到吧,import 也是解构赋值🤓!

注意事项

已定义变量的解构赋值

如果要对一个已经定义的变量使用解构赋值,那么使用类似下面的语法:

const object = { age: 18 };

let age;

({ age } = object);
age === 18;

理由很简单,{ 大括号在行首时,解释器会认为这是一个块级代码,而非赋值语句。

IInfinity

IInfinity

大道虽简,知易行难。
CN