如果你查看我的常规 JavaScript 代码,会看到到处都有解构。
读取对象属性和访问数组项是常见的操作。结构使这些操作变得更加轻松和简洁。
在本文中,除了基本用法之外,我还将会介绍在 JavaScript 中 5 种有趣的解构用法。
通常交换两个变量的方法需要一个附加的临时变量。让我们看一个简单的场景:
let a = 1;
let b = 2;
let temp;
temp = a;
a = b;
b = temp;
a; // => 2
b; // => 1
temp
是保存
a
的值的临时变量。然后,为
a
分配
b
的值,最后为
b
分配
temp
的值。
let a = 1;
let b = 2;
[a, b] = [b, a];
a;
b;
[a,b] = [b,a]
是一个破坏性分配。在右侧,创建一个数组
[b,a]
,即
[2,1]
。数组的第一项
2
分配给
a
,第二项
1
分配给
b
。
尽管仍会创建临时数组,但使用解构分配交换变量更为简洁。
这不是极限。你可以同时交换两个以上的变量。让我们尝试一下:
let zero = 2;
let one = 1;
let two = 0;
[zero, one, two] = [two, one, zero];
zero;
one;
two;
你可以根据需要交换任意多个变量!虽然交换两个变量是最常见的操作。
假设你有一系列可能为空的项目。你要访问数组的第一、第二或第 n 个项目,但是如果该项目不存在,请获取默认值。
const
colors = [];
let firstColor = 'white';
if (colors.length > 0) {
firstColor = colors[0];
}
firstColor;
const colors = [];
const [firstColor = 'white'] = colors;
firstColor;
const [firstColor ='white'] = colors
解构将
colors
数组的第一个元素分配给
firstColor
变量。如果数组在索引
0
处没有任何元素,则将分配默认值
white
。
但是这有更多的灵活性。如果你只想访问第二个元素,也可以这样:
const colors = [];
const [, secondColor = 'black'] = colors;
secondColor;
注意结构左侧的逗号:这意味着第一个元素将被忽略。从
color
数组中为索引为
1
的元素分配了
secondColor
。
当我开始用 React 以及后来的 Redux 时,被迫编写尊重不变性的代码。尽管一开始遇到了一些困难,但后来我看到了它的好处:单向数据流更容易处理。
不变性禁止更改对象。幸运的是,解构可以帮你轻松地以不变的方式完成某些操作。
结合使用
...
rest 操作符可以从数组的开头删除元素:
const numbers = [1, 2, 3];
const [, ...fooNumbers] = numbers;
fooNumbers;
numbers;
解构
[, ...fooNumbers] = numbers
将创建一个新的数组
fooNumbers
,其中包含来自
numbers
的项目,除了第一项。
numbers
数组不会发生变异,从而使操作保持不变。
你可以以不变的方式从对象中删除属性。让我们尝试从对象
big
中删除
foo
属性:
const big = {
foo: 'value Foo',
bar: 'value Bar'
};
const { foo, ...small } = big;
small; // => { bar: 'value Bar' }
big; // => { foo: 'value Foo', bar: 'value Bar' }
解构与 object rest operator 结合使用可创建一个具有
big
所有属性的新对象
small
,唯独不包含
foo
。
在前面的章节中,我们将解构应用于数组。但是你可以解构实现了可迭代协议的任何对象。
许多原生原始类型和对象都是可迭代的:数组、字符串、类型化数组、集合和映射。
const str = 'cheese';
const [firstChar = ''] = str;
firstChar;
不仅限于原生类型,也可以通过实现可迭代协议来自定义解构逻辑。
movies
拥有电影对象的列表。解构
movies
时,最好将电影标题作为字符串。让我们实现一个自定义迭代器:
const movies = {
list: [
{ title: 'Heat' },
{ title: 'Interstellar' }
],
[Symbol.iterator]() {
let index = 0;
return {
next: () => {
if (index this.list.length) {
const value = this.list[index++].title;
return { value, done: false };
}
return { done: true };
}
};
}
};
const [firstMovieTitle] = movies;
console.log(firstMovieTitle);
movies
对象通过定义
Symbol.iterator
方法来实现可迭代的协议。迭代器遍历电影的标题。
遵循可迭代协议,可以将
movies
对象结构为标题,特别是通过读取第一部电影的标题: