完全搞懂 Javascript 中的... [每日前端夜话0xE3]
Posted 前端先锋
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了完全搞懂 Javascript 中的... [每日前端夜话0xE3]相关的知识,希望对你有一定的参考价值。
每日前端夜话,陪你聊前端。
每天晚上18:00准时推送。
正文共:3509 字
预计阅读时间:8 分钟
翻译:疯狂的技术宅
来源:dev.to
曾几何时,ES6/ES2015 对 javascript 语言进行了重大升级。它引入了许多不同的新功能。其中之一就是我们可以用在任何兼容容器(对象、数组、字符串、集合、映射)前面的三个连续点。这些小点使我们能够编写更加优雅和简洁的代码。在本文中我将会解释这三个点的工作原理,并展示最常见的例子。
三个连续的点具有两个含义:展开运算符(spread operator)和剩余运算符(rest operator)。
展开运算符
展开运算符允许迭代器在接收器内部分别展开或扩展。迭代器和接收器可以是任何可以循环的对象,例如数组、对象、集合、映射等。你可以把一个容器的每个部分分别放入另一个容器。
1const newArray = ['first', ...anotherArray];
剩余参数
剩余参数语法允许我们将无限数量的参数表示为数组。命名参数的位置可以在剩余参数之前。
1const func = (first, second, ...rest) => {};
用例
定义是非常有用的,但是很难仅从定义中理解概念。我认为用日常用例会加强对定义的理解。
复制数组
当我们需要修改一个数组,但又不想改变原始数组(其他人可能会使用它)时,就必须复制它。
1const fruits = ['apple', 'orange', 'banana'];
2const fruitsCopied = [...fruits]; // ['apple', 'orange', 'banana']
3
4console.log(fruits === fruitsCopied); // false
5
6// 老方法
7fruits.map(fruit => fruit);
它正在选择数组中的每个元素,并将每个元素放在新的数组结构中。我们也可以使用 map
操作符实现数组的复制并进行身份映射。
唯一数组
如果我们想从数组中筛选出重复的元素,那么最简单的解决方案是什么?
Set
对象仅存储唯一的元素,并且可以用数组填充。它也是可迭代的,因此我们可以将其展开到新的数组中,并且得到的数组中的值是唯一的。
1const fruits = ['apple', 'orange', 'banana', 'banana'];
2const uniqueFruits = [...new Set(fruits)]; // ['apple', 'orange', 'banana']
3
4// old way
5fruits.filter((fruit, index, arr) => arr.indexOf(fruit) === index);
串联数组
可以用 concat
方法连接两个独立的数组,但是为什么不再次使用展开运算符呢?
1const fruits = ['apple', 'orange', 'banana'];
2const vegetables = ['carrot'];
3const fruitsAndVegetables = [...fruits, ...vegetables]; // ['apple', 'orange', 'banana', 'carrot']
4const fruitsAndVegetables = ['carrot', ...fruits]; // ['carrot', 'apple', 'orange', 'banana']
5
6// 老方法
7const fruitsAndVegetables = fruits.concat(vegetables);
8fruits.unshift('carrot');
将参数作为数组进行传递
当传递参数时,展开运算符能够使我们的代码更具可读性。在 ES6 之前,我们必须将该函数应用于 arguments
。现在我们可以将参数展开到函数中,从而使代码更简洁。
1const mixer = (x, y, z) => console.log(x, y, z);
2const fruits = ['apple', 'orange', 'banana'];
3
4mixer(...fruits); // 'apple', 'orange', 'banana'
5
6// 老方法
7mixer.apply(null, fruits);
数组切片
使用 slice
方法切片更加直接,但是如果需要的话,展开运算符也可以做到。但是必须一个个地去命名其余的元素,所以从大数组中进行切片的话,这不是个好方法。
1const fruits = ['apple', 'orange', 'banana'];
2const [apple, ...remainingFruits] = fruits; // ['orange', 'banana']
3
4// 老方法
5const remainingFruits = fruits.slice(1);
将参数转换为数组
Javascript 中的参数是类似数组的对象。你可以用索引来访问它,但是不能调用像 map
、filter
这样的数组方法。参数是一个可迭代的对象,那么我们做些什么呢?在它们前面放三个点,然后作为数组去访问!
1const mixer = (...args) => console.log(args);
2mixer('apple'); // ['apple']
将 NodeList 转换为数组
参数就像从 querySelectorAll
函数返回的 NodeList
一样。它们的行为也有点像数组,只是没有对应的方法。
1[...document.querySelectorAll('div')];
2
3// 老方法
4Array.prototype.slice.call(document.querySelectorAll('div'));
复制对象
最后,我们介绍对象操作。复制的工作方式与数组相同。在以前它可以通过 Object.assign
和一个空的对象常量来实现。
1const todo = { name: 'Clean the dishes' };
2const todoCopied = { ...todo }; // { name: 'Clean the dishes' }
3console.log(todo === todoCopied); // false
4
5// 老方法
6Object.assign({}, todo);
合并对象
合并的唯一区别是具有相同键的属性将被覆盖。最右边的属性具有最高优先级。
1const todo = { name: 'Clean the dishes' };
2const state = { completed: false };
3const nextTodo = { name: 'Ironing' };
4const merged = { ...todo, ...state, ...nextTodo }; // { name: 'Ironing', completed: false }
5
6// 老方法
7Object.assign({}, todo, state, nextTodo);
需要注意的是,合并仅在层次结构的第一级上创建副本。层次结构中的更深层次将是相同的引用。
将字符串拆分为字符
最后是字符串。你可以用展开运算符把字符串拆分为字符。当然,如果你用空字符串调用 split 方法也是一样的。
1const country = 'USA';
2console.log([...country]); // ['U', 'S', 'A']
3
4// 老方法
5country.split('');
总结
在本文中我们研究了 Javascript 中展开运算符的许多用例。如你所见,ES6 不仅使编写代码的效率更高,而且还引入了一些有趣的方法来解决长期存在的问题。现在所有主流浏览器都支持新语法。在你阅读本文时,就可以在浏览器的控制台中尝试上述所有例子。无论用哪种方式,你现在就可以把展开运算符和剩余参数用到自己的代码中。
原文:https://dev.to/blacksonic/the-tale-of-three-dots-in-javascript-4287
下面夹杂一些私货:也许你和高薪之间只差这一张图
2019年京程一灯课程体系上新,这是我们第一次将全部课程列表对外开放。
愿你有个好前程,愿你月薪30K。我们是认真的 !
长按二维码,加大鹏老师微信好友
拉你加入前端技术交流群
唠一唠怎样才能拿高薪
往期精选
小手一抖,资料全有。长按二维码关注前端先锋,阅读更多技术文章和业界动态。
以上是关于完全搞懂 Javascript 中的... [每日前端夜话0xE3]的主要内容,如果未能解决你的问题,请参考以下文章