如何实现JavaScript的Map和Filter函数?

原创 Fundebug 随笔 Fundebug 61阅读 2018-11-15 11:20:32 举报

译者按: 鲁迅曾经说过,学习JavaScript最好方式莫过于敲代码了!

为了保证可读性,本文采用意译而非直译。另外,本文版权归原作者所有,翻译仅用于学习。

这篇文章面向那些已经熟练使用for循环,但对Array.mapArray.filter并没有特别理解的开发者。本文将会手把手去实现这两个函数,来深入理解它们的工作原理。

Array.map

Array.map通过对输入的数组中每一个元素进行变换,返回由变换后的元素按序组成的新数组。原始数组的值不会被修改。假设我们相对一个数组中的每一个元素乘以3,使用for循环可以这样写。

for循环

接下来我们将这个for循环抽象成一个函数。

multiplyByThree函数

现在我们继续深化这个抽象思路,将multiplyByThree中对每一个元素乘以3部分抽象为一个新的函数。

这样有什么好处呢?设想如果我们想对每一个元素乘以5,或则10,我们还要把整个for循环写一遍吗!
如果我们对timesThree函数稍作修改,就可以轻松的复用很多代码。

multiply函数

我们将:

重构为:

我们将multiplyByThree重命名为multiply,并增加了一个参数。该参数是一个函数,定义了数组元素的变换规则。通过定义一个timesThree函数来达到实现对每一个数组元素乘以3的目的。

有何优点呢?我们可以很简单定义任何变换:

Map

我们进一步抽象:

multiply改为map, multiplyFunction改为transform:

我们可以将任何对单个元素操作的函数传入map函数。比如,我们将所有字符都变换成大写:

Array.map

我们定义的map函数和原生的Array.map还是有区别的:数组不再需要作为第一个参数传入,而是在点(.)的左侧。如果使用我们定义的map函数,如下:

如果使用自带的Array.map函数,则如下所示:

Arrary.map参数解析

除了变换函数外,Array.map还可以接收其它两个参数: 数组索引(index), 原始的数组。

因此,你可以再变换函数中使用索引和原始的数组。比如:你想要将一个列表变为带序号的列表,则需要使用索引(index)参数:

因此,我们自己实现的map函数也应该支持这两个参数:

当然,Array.map函数还有一些错误检查和执行优化的代码,我们定义的map只编码了核心功能。

Array.filter

Array.filter将数组中不满足条件的元素过滤,我们可以用for循环加上Array.push来实现。

for-loop

下面这段JS代码将所有大于5的元素筛选出来:

我们可以抽象这段代码,定义为一个函数:

进一步抽象,将过滤条件抽出来:

将过滤条件函数作为参数传入:

大功告成!我们可以使用如下代码来取出所有大于5的元素:

Array.filter

我们将filterBelow重命名为filter, greaterThan重命名为testFunction:

这就是一个基本的Array.filter函数了!

同样,Array.filter也有索引(index)和原始数组这两个额外参数。

关于Fundebug

Fundebug专注于JavaScript、微信小程序、微信小游戏、支付宝小程序、React Native、Node.js和Java实时BUG监控。 自从2016年双十一正式上线,Fundebug累计处理了7亿+错误事件,得到了Google、360、金山软件、百姓网等众多知名用户的认可。欢迎免费试用!

版权声明

转载时请注明作者Fundebug以及本文地址:
https://blog.fundebug.com/2017/07/26/master_map_filter_by_hand_written/

评论 ( 0 )
最新评论
暂无评论

赶紧努力消灭 0 回复