看看我的常规JavaScript代码,我发现解构赋值无处不在。
读取对象属性和访问数组项是常见的操作。解构分配使这些操作变得更加容易和简洁。
在这篇文章中,我将描述JavaScript中解构的5个有趣的用途,除了基本用法之外。
交换 2 个变量的常用方法需要一个额外的临时变量。让我们看一个简单的场景:
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; // => 2
b; // => 1
[a, b] = [b, a]
是解构赋值。在右侧,将创建一个数组,即 。此数组的第一项分配给 ,第二项分配给 。[b, a]
[2, 1]
2
a
1
b
尽管仍可创建临时数组,但使用解构赋值交换变量更简洁。
这不是限制。您可以同时交换 2 个以上的变量。让我们试试:
let zero = 2;
let one = 1;
let two = 0;
[zero, one, two] = [two, one, zero];
zero; // => 0
one; // => 1
two; // => 2
您可以根据需要交换任意数量的变量!虽然,交换2个变量是最常见的情况。
您有一个可能为空的项目数组。您希望访问数组的第一个、第二个或第 n 个项目,但如果该项目不存在,则获取默认值。
通常,您将使用数组的 length 属性:
const colors = [];
let firstColor = 'white';
if (colors.length > 0) {
firstColor = colors[0];
}
firstColor; // => 'white'
幸运的是,数组解构可以帮助您以同样更短的方式实现:
const colors = [];
const [firstColor = 'white'] = colors;
firstColor; // => 'white'
const [firstColor = 'white'] = colors
解构将数组的第一个元素赋给变量。如果数组在索引处没有任何元素,则分配默认值。firstColor
colors
0
'white'
但是灵活性要大得多。如果您只想访问第二个元素,那也是可能的:
const colors = [];
const [, secondColor = 'black'] = colors;
secondColor; // => 'black'
请注意解构左侧的逗号:这意味着忽略第一个元素。 与数组中的索引处的元素一起分配。secondColor
1
colors
当我开始使用 React 和后来的 Redux 时,我被迫编写尊重不可变性的代码。虽然一开始遇到了一些困难,但后来我看到了它的好处:处理单向数据流更容易。
不可变性禁止改变对象。幸运的是,解构可以帮助您以不可变的方式轻松实现某些操作。
与 rest 运算符结合使用的析构从数组的开头删除元素:...
const numbers = [1, 2, 3];
const [, ...fooNumbers] = numbers;
fooNumbers; // => [2, 3]
numbers; // => [1, 2, 3]
解构将创建一个新数组,其中包含除第一个数组之外的项。[, ...fooNumbers] = numbers
fooNumbers
numbers
numbers
数组不会发生突变,使操作保持不可变。
可以采用相同的不可变方式从对象中删除属性。让我们尝试从对象中删除属性:foo
big
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 运算符结合使用,将创建一个新对象,其中所有属性均来自 ,仅不带 。smallbigfoo
在前面的部分中,解构已应用于数组。但是,您可以取消构造实现可迭代协议的任何对象。
许多本机基元类型和对象都是可迭代的:数组、字符串、类型化数组、集合和映射。
例如,可以将字符串分解为字符:
const str = 'cheese';
const [firstChar = ''] = str;
firstChar; // => 'c'
您不仅限于本机类型。可以通过实现可迭代协议来自定义析构逻辑。
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); // => 'Heat'
movies
对象通过定义方法实现可迭代协议。迭代器循环访问电影的标题。Symbol.iterator
符合可迭代协议允许将对象解构为标题,特别是通过读取第一部电影的标题:。movies
const [firstMovieTitle] = movies
天空是使用迭代器进行解构时的极限。
根据我的经验,按属性对对象进行解构比数组解构更频繁。
对象的解构看起来非常简单:
const movie = { title: 'Heat' };
const { title } = movie;
title; // => 'Heat'
const { title } = movie
创建一个变量,并为其分配属性的值。title
movie.title
当第一次阅读有关对象析构的信息时,我有点惊讶,您不必静态地知道属性名称。您可以使用动态属性名称取消构造对象!
为了了解动态解构的工作原理,让我们编写一个问候语函数:
function greet(obj, nameProp) {
const { [nameProp]: name = 'Unknown' } = obj;
return `Hello, ${name}!`;
}
greet({ name: 'Batman' }, 'name'); // => 'Hello, Batman!'
greet({ }, 'name'); // => 'Hello, Unknown!'
greet()
函数使用 2 个参数调用:对象和属性名称。
在内部,解构赋值使用方形制动器读取动态属性名称。该变量接收动态属性值。greet()
const { [nameProp]: name = 'Unknown' } = obj
[nameProp]
name
更好的是,您可以指定一个默认值,以防该属性不存在。'Unknown'
如果要访问对象属性和数组项,则解构效果很好。
除了基本用法之外,数组解构还便于交换变量,访问数组项,执行一些不可变的操作。
JavaScript 提供了更大的可能性,因为您可以使用迭代器定义自定义解构逻辑。