原文标题:5 Interesting Uses of JavaScript Destructuringjavascript
原文连接:dmitripavlutin.com/5-interesti…java
按期回顾我写的JS代码,我发现解构运算无处不在。 获取对象的属性和访问数组内容是都是很经常使用的操做。而解构运算使得这些操做变得很是简单明了。 在这篇文章中,我将会讲解JS解构不一样于常见用法的五种使用技巧。数组
常见的交互两个变量值的方法都须要借助一个额外的变量,看一个简单的例子:bash
let a = 1;
let b = 2;
let temp;
temp = a;
a = b;
b = temp;
a; // => 2
b; // => 1
复制代码
temp
是一个临时变量,在例子中存储了变量a
的值,b
的值赋给了a
,最后把temp
的值赋给了b
。 解构运算使得交换变量的值变得很是简单,不须要借助第三个临时变量:函数
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
。 即便这种方式仍然建立了一个临时数组,可是解构赋值对于交换变量的值仍然是很是高效简单的方式。 这种方式并无什么限制。你还能够同时交互更多的变量值,好比:ui
let zero = 2;
let one = 1;
let two = 0;
[zero, one, two] = [two, one, zero];
zero; //=> 0
one; //=> 1
two; //=> 2
复制代码
你能够交换任意数量的变量值,只是两个变量值的交换的状况更加常见。this
有一个数组,这个数组有多是空的。有一种需求是访问任意位置数组元素,若是这个位置为空,则返回一个默认值。 一般状况下有的人可能会使用数组的length
属性作判断:spa
const colors = [];
let firstColor = "white";
if (colors.length > 0) {
firstColor = colors[0];
}
firstColor; //=> "white"
复制代码
幸运的是,数组解构能够更快捷高效的实现相同的效果:rest
const colors = [];
const [firstColor = "white"] = colors;
firstColor; //=> "white"
复制代码
const [firstColor = "white"] = colors;
将colors
数组的第一个元素赋值给了变量firstColor
。若是这个数组的下标为0的位置上没有任何元素(注:为undefined时即认为为空),white
将做为默认值赋值给firstColor
。 数组解构是很是灵活的,若是你只想访问数组的第二个元素,方法以下所示:code
const colors = [];
const [, secondColor = "black"] = colors;
secondColor; //=> "black"
复制代码
在解构表达式的左边写一个逗号:意味着数组的第一个元素被忽略掉。colors
数组下标为1的元素被解构赋值给了变量secondColor
。
从我开始使用React,到后来的Redux,我被迫开始写一些遵循不可变原则的代码。刚开始的时候确实有点不适应,不事后来我就意识到了这种方式的好处:它使得处理单向数据流更加容易。 不可变原则禁止修改对象。幸运的是,解构能够帮助你在遵循不可变原则的同时完成这些操做。 将解构与展开运算符(rest operator)结合使用来移除数组的第一个元素:
const numbers = [1,2,3];
const [, ...fooNumbers] = numbers;
fooNumbers; //=> [2, 3]
numbers; //=> [1,2,3]
复制代码
这个解构操做[, ...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" }
复制代码
上述方法将解构与对象展开运算符结合起来使用,建立了一个新的对象small
,这个新对象包含big
对象除了foo
属性以外的全部属性。
在前面几部份内容中,都是解构的数组。实际上解构运算是能够用于全部的可迭代对象的。 许多原生的基础类型和对象都是可迭代的,例如数组,类数组,字符串,set
集合和map
集合。 例如,你能够把字符串解构成单个字符:
const str = "cheese";
const [firstChar = ""] = str;
firstChar; //=> 'c'
复制代码
固然解构不单单限于原生可迭代的那几种类型。解构能够被用于全部实现了迭代接口(iterable protocol)的对象。 以下所示,movies
包含一个movie对象列表。咱们想要解构movies
对象的时候,能够获取到电影的title
这个字符串。实现这个操做首先须要自定义一个迭代器:
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
方法实现了一个迭代器。这个迭代器能够迭代全部电影的title
属性。 咱们在movies
对象上遵循了迭代接口实现,从而实现了经过解构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="Unknow" } = obj;
return `Hello, ${name}!`;
}
greet({ name: "Batman" }, "name"); //=> Hello, Batman!
greet( {}, "name" ); //=> Hello, Unknow!
复制代码
greet()
被调用时须要传递两个参数,一个是对象,一个是属性名称。 在greet()
函数内部,解构表达式const { [nameProp]: name="Unknow" } = obj;
使用中括号[nameProp]
读取动态属性的名称。name
变量接收动态属性的值。 更好的作法就是你能够指定一个默认的值Unknow
以防属性不存在的状况。
解构能够帮助你更方便快捷的访问对象属性和数组元素。 除了基本用法以外,数组解构还能够方便的交换变量,访问数组元素,作一些遵循不可变原则的操做。 JavaScript提供了更多的可能性,由于你能够经过扩展迭代器实现自定义的解构逻辑。