在JavaScript中为什么应该用map和filter替换forEach?

时间: 2018-09-17阅读: 1475标签: Array

当你需要拷贝一个数组的全部或者部分到一个新数组的时候,优先使用map和filter而不是forEach。

咨询工作的好处之一是我可以看到无数的项目。这些项目在规模、使用的编程语言和开发人员的能力方面差别很大。虽然有很多我觉得应该废弃的模式,但是在JavaScript中,我觉得最应该废弃的是使用forEach创建新的数组。事实上,这个模式非常简单,看起来如下所示:

const kids = [];
people.forEach(person => {
  if (person.age < 15) {
    kids.push({ id: person.id, name: person.name });
  }
});

上面代码做的操作就是处理包含所有人的数组,并找出年龄小于15的人。然后把每一个符合条件的’孩子‘的部分属性组成的新对象添加到kids数组中。

虽然可以满足需求,但是有一种势在必行的编码方式(查看编程范式)。所以,你可能会想哪里出了问题?要理解这一点,让我们先熟悉两个”朋友“:map和filter。


map & filter

map和filter是在2015年作为ES6特征集的一部分引入到JavaScript中的。它们是数组的方法,允许在JavaScript中使用更函数式的编码风格。和在函数式编程的世界里一样,这两个方法也不会修改原数组,而是返回一个新数组。它们都接受一个类型是函数的单一变量。然后,这个函数会在原数组的每一项上被调用去产生最终结果。让我们看下这两个方法做了什么:

  • map:每一项调用函数的返回结果会放在这个方法返回的新数组里。

  • filter:每一项调用函数的返回结果决定这一项是否会被该方法返回的数组包含。

类似的还有一个方法,只是很少被用到,也就是reduce

以下是查看实际操作的简单例子:

const numbers = [1, 2, 3, 4, 5];
const doubled = numbers.map(number => number * 2); // [2, 4, 6, 8, 10]
const even = numbers.filter(number => number % 2 === 0); // [2, 4]

现在我们知道map和filter是干什么的了,接下来我们会看到一个例子,在这个例子中会展示我更偏向于怎么写前面的例子:

const kids = people
  .filter(person => person.age < 15)
  .map(person => ({ id: person.id, name: person.name }));

如果你想了解用在map方法里面的lambda表达式的语法,查看这个Stack Overflow回答了解详情。

所以,这种实现方式的好处如下:

  • 关注点分离:过滤和改变数据的格式是两个不相关的关注点,对两个关注点分别使用各自的方法可以达到关注点分离的目的。

  • 易于测试:两种目的都使用了简单的纯函数,使得各种行为的单元测试变得简单。值得一提的是最初的实现版本并不是纯粹的,因为依赖一些作用域外边的状态(keys数组)。

  • 可读性:因为这两个方法有明确的目的,一个是过滤数据,一个是改变数据的格式,所以很容易看出对数据做了哪些处理。尤其是像reduce这样的同类函数。

  • 异步编程:forEach和async/await不能很好地结合在一起。但是map提供了一种有用的模式,可以和promises和async/await一起使用。更多关于这一点的内容会在下一篇博客中介绍。

同样值得注意的是,当你想产生副作用的时候,比如修改全局状态,不要使用map。尤其是当map方法的返回值并不会被保存或者使用的时候。


总结

使用map和filter有很多好处,比如关注点分离、易于测试、可读性和异步编程的支持。因此,对我来说这是一个明智的选择。但是,我经常遇到使用forEach的开发人员。虽然函数式编程可能有点儿吓人,但是这些方法并没有什么好害怕的,即使它们有一些函数式编程的特征。map和filter在响应式编程中也被大量的用到。由于RxJS,现在响应式编程在JavaScript中被越来越多的用到。但请注意,它们可能会永久地改变你的编码方式。


原文链接: gofore.com  
翻译来源:www.zcfy.cc


站长推荐

1.云服务推荐: 国内主流云服务商,各类云产品的最新活动,优惠券领取。地址:阿里云腾讯云华为云

链接: http://www.fly63.com/article/detial/1083

js实现一维数组转换为树形结构数组

在设计树形结构的数据时候,数据库一般为:id,name,parent...如果后端不处理直接返给前端,前端就需要把这个一维数组转换为树形结构数组。下面整理了下如何通过js实现一维数组转换为树形结构数组。

js中数组创建的多种方式,数组中常用方法总汇

javascript创建数组的几种方式:1、字面量形式直接创建数组,2、Array构造函数创建数组。js数组常用的方法有哪些:join(),push()和pop(),shift() 和 unshift(),sort(),reverse(),concat()等

es6之Array.of()和Array.from()

es6新增了二种方法:Array.of()和Array.from(),它们有什么用途呢?在平时的开发中能给我们带来什么方便呢?本篇将从一个创建数组的小问题开始,逐步揭开它们的面纱。

数组去重_原生js对普通数组去重算法的7种方法总结

JavaScript实现普通数组去重,讲解各种算法的思想和改进方法,已经他们的优缺点...利用数组的reduce方法,使用了filter方法,利用ES6去重,相对来说更为简单

arguments转化成Array数组的方法

简单说一下arguments,arguments 就是函数内一个內建对象,它包含函数接收到的所有变量;所以,在实际开发中,我们使用arguments可以很方便的获取到所有的实参,并且也需要对其使用是写数组的方法

JS取出两个数组中的不同或相同元素

concat() 方法:用于连接两个或多个数组。Array filter() 方法:创建一个新的数组,新数组中的元素是通过检查指定数组中符合条件的所有元素。indexOf() 方法:可返回某个指定的字符串值在字符串中首次出现的位置。

JS实现遍历不规则多维数组的方法

这篇文章主要介绍了JS实现遍历不规则多维数组的方法,涉及javascript数组递归遍历相关实现与使用技巧,需要的朋友可以参考下

js判断对象、数组是否为空

做项目时想要根据判断对象是否为空,然后执行不同的操作,下面就整理下如何实现,针对数组和对象的通用方法。方法一:isPrototypeOf()和length判断、方法二:hasOwnProperty、方法三:利用JSON.stringify()方法

js实现交换数组元素位置的方法总汇

交换数组元素位置是开发项目中经常用到的场景,总结下用过的几种方式:第三方变量、splice方法、解构赋值

Array.slice 8种不同用法

在深入研究一些更高级的用法之前,让我们看一下slice方法的基础知识。如MDN文档,slice 是数组上的一个方法,它最多有两个参数,从该索引处开始提取原数组中的元素,如果该参数为负数,则表示从原数组中的倒数第几个元素开始提取

点击更多...

内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!