关于JS解构的5种有趣用法


Posted in Javascript onSeptember 05, 2019

前言

原文标题:5 Interesting Uses of JavaScript Destructuring

原文链接:dmitripavlutin.com/5-interesti…

定期回顾我写的JS代码,我发现解构运算无处不在。

获取对象的属性和访问数组内容是都是很常用的操作。而解构运算使得这些操作变得非常简单明了。

在这篇文章中,我将会讲解JS解构不同于常见用法的五种使用技巧。

1. 交换变量

常见的交互两个变量值的方法都需要借助一个额外的变量,看一个简单的例子:

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。

即使这种方式仍然创建了一个临时数组,但是解构赋值对于交换变量的值仍然是非常高效简单的方式。

这种方式并没有什么限制。你还可以同时交互更多的变量值,比如:

let zero = 2;
let one = 1;
let two = 0;
[zero, one, two] = [two, one, zero];
zero; //=> 0
one; //=> 1
two; //=> 2

你可以交换任意数量的变量值,只是两个变量值的交换的情况更加常见。

2. 访问数组

有一个数组,这个数组有可能是空的。有一种需求是访问任意位置数组元素,如果这个位置为空,则返回一个默认值。
通常情况下有的人可能会使用数组的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;将colors数组的第一个元素赋值给了变量firstColor。如果这个数组的下标为0的位置上没有任何元素(注:为undefined时即认为为空),white将作为默认值赋值给firstColor。
数组解构是非常灵活的,如果你只想访问数组的第二个元素,方法如下所示:

const colors = [];
const [, secondColor = "black"] = colors;
secondColor;  //=> "black"

在解构表达式的左边写一个逗号:意味着数组的第一个元素被忽略掉。colors数组下标为1的元素被解构赋值给了变量secondColor。

3. 不可变操作

从我开始使用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属性之外的所有属性。

4. 解构可迭代的值

在前面几部分内容中,都是解构的数组。实际上解构运算是可以用于所有的可迭代对象的。

许多原生的基础类型和对象都是可迭代的,例如数组,类数组,字符串,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;

解构用法的上限就是没有上限。

5. 解构动态属性

在我的经验中,解构一个对象的属性要远比解构一个数组的情况更多。

解构对象看起来非常的简单:

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以防属性不存在的情况。

6. 总结

解构可以帮助你更方便快捷的访问对象属性和数组元素。

除了基本用法之外,数组解构还可以方便的交换变量,访问数组元素,做一些遵循不可变原则的操作。

JavaScript提供了更多的可能性,因为你可以通过扩展迭代器实现自定义的解构逻辑。

好了,以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对三水点靠木的支持。

Javascript 相关文章推荐
走出JavaScript初学困境—js初学
Dec 29 Javascript
filters.revealTrans.Transition使用方法小结
Aug 19 Javascript
jquery获取table中的某行全部td的内容方法
Mar 08 Javascript
jquery获得option的值和对option进行操作
Dec 13 Javascript
js实现适用于素材网站的黑色多级菜单导航条效果
Aug 24 Javascript
js实现模拟银行卡账号输入显示效果
Nov 18 Javascript
利用jQuery插件imgAreaSelect实现图片上传裁剪(同步显示图像位置信息)
Dec 02 Javascript
react实现菜单权限控制的方法
Dec 11 Javascript
React BootStrap用户体验框架快速上手
Mar 06 Javascript
vue-router 手势滑动触发返回功能
Sep 30 Javascript
JavaScript实现HSL拾色器
May 21 Javascript
Antd的Table组件嵌套Table以及选择框联动操作
Oct 24 Javascript
vue draggable resizable gorkys与v-chart使用与总结
Sep 05 #Javascript
JavaScript获取某一天所在的星期
Sep 05 #Javascript
layui table设置某一行的字体颜色方法
Sep 05 #Javascript
微信小程序HTTP接口请求封装代码实例
Sep 05 #Javascript
layui table去掉右侧滑动条的实现方法
Sep 05 #Javascript
微信小程序下拉加载和上拉刷新两种实现方法详解
Sep 05 #Javascript
layui动态加载多表头的实例
Sep 05 #Javascript
You might like
c#中的实现php中的preg_replace
2009/12/21 PHP
PHP实现的比较完善的购物车类
2014/12/02 PHP
php无限级评论嵌套实现代码
2018/04/18 PHP
PHP实现基于状态的责任链审批模式详解
2019/05/31 PHP
javascript window对象属性整理
2009/10/24 Javascript
Jquery css函数用法(判断标签是否拥有某属性)
2011/05/28 Javascript
jQuery在IE下使用未闭合的xml代码创建元素时的Bug介绍
2012/01/10 Javascript
nodejs简单实现中英文翻译
2015/05/04 NodeJs
javascript判断网页是关闭还是刷新
2015/09/12 Javascript
不依赖Flash和任何JS库实现文本复制与剪切附源码下载
2015/10/09 Javascript
jquery.cookie.js用法实例详解
2015/12/25 Javascript
总结Node.js中的一些错误类型
2016/08/15 Javascript
js代码实现下拉菜单【推荐】
2016/12/15 Javascript
vue2 自定义动态组件所遇到的问题
2017/06/08 Javascript
基于jQuery实现的单行公告活动轮播效果
2017/08/23 jQuery
使用ef6创建oracle数据库的实体模型遇到的问题及解决方案
2017/11/09 Javascript
分析JS单线程异步io回调的特性
2017/12/01 Javascript
Layui动态生成select下拉选择框不显示的解决方法
2019/09/24 Javascript
vue 扩展现有组件的操作
2020/08/14 Javascript
[52:37]完美世界DOTA2联赛循环赛 Forest vs DM BO2第一场 10.29
2020/10/29 DOTA
Python类的继承和多态代码详解
2017/12/27 Python
PyTorch快速搭建神经网络及其保存提取方法详解
2018/04/28 Python
python数据结构学习之实现线性表的顺序
2018/09/28 Python
Python 实现中值滤波、均值滤波的方法
2019/01/09 Python
python实现合并多个list及合并多个django QuerySet的方法示例
2019/06/11 Python
python opencv对图像进行旋转且不裁剪图片的实现方法
2019/07/09 Python
Pytorch使用PIL和Numpy将单张图片转为Pytorch张量方式
2020/05/25 Python
CSS3 transform的skew属性值图文详解
2014/07/21 HTML / CSS
数字天堂软件测试面试题
2012/12/23 面试题
应届生护士求职信
2013/11/01 职场文书
先进班级集体事迹材料
2014/01/30 职场文书
领导干部考察材料
2014/02/08 职场文书
信息与工商管理职业规划范文:为梦想而搏击
2014/09/11 职场文书
装修公司管理制度
2015/08/05 职场文书
Java生成日期时间存入Mysql数据库的实现方法
2022/03/03 Java/Android
baselines示例程序train_cartpole.py的ImportError
2022/05/20 Python