少侠们好~

今天和大家分享一篇关于JS数组里面的map,filter,reduce相关函数的知识,

相信少侠们肯定或多或少都了解过一些相关知识,特别对于map和filter这种很常用的函数的用法,可能已经信手拈来了,

但是~

少侠,

你真的确定,你目前所使用的方式,就是它们的正确使用姿势吗?

如果想知道所作的选择是否明智,就看你在清楚知道将会付出什么代价的情况下,是否依然选择那样做。

————《黑客帝国3》


首先,让我们从最一个比较简单的例子开始:

这里有一个从1到10的数组:

现在,如果少侠你需要取出中间的奇数,你会怎么做呢?

这个问题不难,有的少侠可能会使用for循环来过滤出偶数,某些少侠可能会使用while循环,又或是使用数组自带的filter方法。

这里,我们先不考虑使用for和while这些迭代方法,我们选择使用数组自带的filter方法,如果使用filter方法的话,

少侠你的代码大概可能会是这样的:

还是挺简单的对吧?

相信大部分少侠都能很轻松完成。

在filter函数内部,我们使用 num % 2 !== 0 来判断 是否是一个奇数,如果是一个奇数,就过滤出来。

在这里,有的少侠可能就会想到,如果把这个判断过程单独分成一个函数,会方便一些,也方便以后的修改扩展。

比如,单独写成一个 isOdd函数:

然后在filter里面使用这个函数,是吧?

但是!

一些少侠这里就会开始犯一个天真的错误了,

你可能会写成下面这样:

看见这样的代码,有的少侠可能会说,天辰,这样写没有什么问题啊,我也测试过了,结果都是正确的,怎么就天真了?

没错,结果是正确的,

但是,你每次在filter里面都额外调用了一次并不一定需要的函数。

也就是包裹着 return isOdd(num)的那个外层箭头函数。

如果你还没看出来问题的话,先看看这个例子:

这里的sayHello接受一个字符串name, 然后返回 ‘hello’ + name.

helpSayHello同样接受一个字符串name,然后用这个name 调用 sayHello, 得到返回的 ‘hello’ + name.

那么,少侠你看看,下面两句代码结果有什么区别呢?

我们干嘛不直接调用sayHello呢?

“这样啊,大概理解了,但是天辰你告诉我,鸽子为什么那么大? 到底哪里调用了2次了?”

(不知道鸽子为什么那么大什么意思的点击这里查看~)

“。。。。。。”

好吧,那换个角度,

现在发现了没?

filter里面那个函数是不是和isOdd一模一样?

所以,我们直接把isOdd放进去就可以了:

“道理我懂了,但是谁能告诉我,鸽子到底为什么那么大? 为什么之前那样会多调用一次函数?”

“。。。。。。。算了,接着看下面的内容吧”

如果要把nums里面的数字翻倍,用map函数,又该怎么做呢?

聪明的少侠这次肯定一下就明白了:

好了,既然现在我们知道了如何从nums数组里面过滤出奇数,如何翻倍里面的数字,那么,接下来我们就更进一步:

从nums里面过滤出所有奇数,并翻倍这些奇数。

这个问题也不难是吧?

让我猜一下,一些少侠应该会写成下面这样:

如果我们还想继续算出所有奇数翻倍后的和的话:

嗯,一个串一个看起来很酷是吧? 最后的结果也是正确的。

但是。。。

少侠你依然比较天真!

这样串起来的后果就是,我们会遍历3次数组,filter的时候遍历一次,map的时候遍历一次,reduce的时候再遍历一次。

现在数组只有10个数字,影响还不大,但是如果是很大的数组,比如100万个数字,遍历3遍的话,那么就会多访问150万次,

150万次什么概念?

少侠你有150万存款嘛?

更坏的情况会是当你习惯这种方式后,你可能会连接更多的函数。。。。

array
.map(fn1)
.map(fn2)
.filter(fn4)
.filter(fn5)
.forEach(fn6)
.....

所以,这种方式其实不算是一种很好的方式,

到这里有的少侠可能要问了,如果这种方式不是很好,有什么更好的方式呢? 我要怎么去找到更好的方式呢?

实际上,

要找到更好的方式,这里我们首先可以尝试的是

凭感觉。。。。

想象一下,如果让你自己从中间取出所有奇数,翻倍,并求和,你会觉得怎么做简单一些呢?

是不是觉得下面这样才比较正常?

首先,从第一个数字开始,如果它是奇数,就拿出来,翻倍,然后找个地方放起来,

接着,

继续看第二个数字,如果是偶数,就跳过,如果是奇数,就拿出来,翻倍,然后和开始的翻倍后的奇数加起来,找个地方放起来。

接着看第三个数字,以此类推,只要是奇数,就翻倍,然后和之前的结果加起来。

直到我们找寻到最后一个数字,就可以算出最终结果了,

对吧?我们并不需要再回头看了。

所以,这样才是正确的方式。

如果使用迭代的话,就是下面这样:

没错,通常这样才是正常的操作。

但是,

这样的代码不太方便,

少侠你肯定也不想每次都写这么一大堆for循环语句吧?

所以,我们可以先试着继续优化一下。

我们首先试着用一个叫做magic(魔法)的函数把这些步骤包裹起来:

现在看起来好多了,不过,magic内部的操作看起来不是很清晰,

其他少侠看见了可能很难一眼就明白magic函数在做什么,

我们可以试着把里面的一些步骤分成更小的函数:

去掉注释,换个稍微简洁点的写法:

现在比较简洁也比较清晰了,不过,假如我们现在要计算是偶数而不是奇数怎么办呢?

或者如果更复杂些,如果是偶数,就反过来,除以二,然后求和,又该怎么办呢?

难道我们又要复制一次magic函数,然后改动for循环里面的逻辑吗?

也许,我们可以把for循环内部的逻辑单独提取成一个外部函数!

但是,

少侠们注意了!

这里的问题是,在内部的时候,for可以通过闭包规则,访问到array, 访问到array[i],以及sum,

而当我们把magicFriend函数放在外面之后,它没办法再访问到magic内部的array, array[i],以及sum了,

因为之前所有逻辑都在magic函数内部,可以通过闭包规则访问到所需变量,现在不行了。

那么怎么解决呢?

很简单~

这里我们真正关心的是,如何通过其他方式获取到之前通过闭包获取到的参数。

既然闭包的规则没办法帮助我们获取到所需参数,我们就换一个能帮我们获取到对应参数的规则,这里我们就换成通过函数参数来获取:

当然,现在在magic内部,for循环里面严重依赖当前作用域中一个叫做magicFriend的函数,如果当前作用域中的magicFriend函数不见了,magic函数就没办法正常运行了,

为了更灵活,我们可以把magicFriend也换成通过参数传递给magic。

等一等!

还有个问题。。。

万一我们希望sum从100开始相加呢?

算了,那就把sum也提取出来,通过参数传进去吧。。。

到这里了,有些少侠可能要问了!

天辰你到底有完没完了?

整这些花里胡哨的有什么用?

别急! 少侠~ 接下来就是见证奇迹的时刻!

首先,我们给代码里面部分函数和参数改一下名字:

是不是有点眼熟了? 接着,我们换成数组自带的reduce函数:

最后回到我们上面的问题:

完全OK!

这次我们用reduce只遍历了一次数组就完成了之前的操作!

现在知道为什么之前要把reduce叫做magic(魔法)了吧!

不过~~

到这里, 有的少侠可能会觉得有点奇怪,那么之前的filter和map呢? 为什么现在就不需要它们了呢?

针对这个问题,天辰我的答案是:

因为我们根本就不是在单纯地执行map或filter操作~

如果少侠你真的只是单纯地想把一堆数据,映射成另一对数据,才是用map。

如果少侠你真的只是单纯地想过滤出一些数据,才是用filter。

除此之外,如果你既要过滤(filter)一些东西,同时又要映射(map)一些东西,

那么,少侠你实际上既不是在做map操作,也不是做filter操作,这个时候,请考虑采用reduce(magic)!

不行! 说好了只使用map,多一个filter,多一个map,都不算map!

好了,

恭喜你,少侠!

你成功发现并阅读完了这篇文章~

首先~

谢谢少侠你看到了这里,

然后~

不管少侠你现在处于什么阶段,希望你都能从中有所收获。

那么现在要结束了?

当然不行!

不管你们下次还有没有兴趣,按照惯例,在结束之前必须留个悬念吊一下胃口~

所以,提前预告一下下期内容。。。

下一次,天辰会和少侠们分享一个有趣的武器,

这个武器是天辰费了很大劲从救赎(JS)大陆获取到的,能够更酷(更装逼)地处理我们今天遇到的问题,

虽然可能需要少侠你有一定的修为才能使用,

但是~

不管怎样,我相信少侠你最终肯定能掌握它。

一些你可能关心的问题:

1、天辰,你说的这些,能帮助我涨工资吗?

说能的话显得有点装逼!但是,少侠如果你能像这样坚持不断学习的话,相信你以后不仅能涨工资,还能给别人发工资!

2、天辰,我不关心工资,我关心的是,了解这些能帮助我找到女朋友吗?

看见这个狗头了没?

少侠留步! 你可能一直都误解了map,filter和reduce.相关推荐

  1. 武侠争霸·英雄帖在此,少侠留步

    过期儿童欢乐多 2018武林大会 组建帮派争霸对擂,评选天下第一帮 打破隔离融入其中 成有成的喜悦/输有输的趣味(比如关爱的眼神) 来看看闲鱼技术同学们的风采吧 恩恩爱爱,牵绳荡悠悠 15位工程狮同时 ...

  2. 道友请留步,且看PaddlePaddle入手深度学习成为一名炼丹师

    目录 道友请留步 求道初体验 金丹大道修炼秘籍 1 道友请留步 要做神仙,快乐无边.点石成金,驾鹤飞仙! 从<封神演义>到<西游记>,中国的神话传说满足了我们对宇宙的浪漫憧憬和 ...

  3. 一步一步跟我学习hadoop(5)----hadoop Map/Reduce教程(2)

    Map/Reduce用户界面 本节为用户採用框架要面对的各个环节提供了具体的描写叙述,旨在与帮助用户对实现.配置和调优进行具体的设置.然而,开发时候还是要相应着API进行相关操作. 首先我们须要了解M ...

  4. HashMap和Hashtable的区别--List,Set,Map等接口是否都继承自Map接口--Collection和Collections的区别...

    面试题: 1.HashMap和Hashtable的区别?HashMap:线程不安全,效率高,键和值都允许null值Hashtable:线程安全,效率低,键和值都不允许null值ArrayList代替V ...

  5. 少侠请留步!这里有你要的技术文章与求职干货

    程序员江湖 "程序员江湖"这个公众号,从创建到现在大抵两个月左右,承蒙各位支持,已经有了好几千的粉丝.期间有很多人问我为什么要做这个号,其实我也一直想聊聊这个话题,所以,今天我就把 ...

  6. 少侠,留步,图片预览术

    少年,我看你骨骼精奇,是万中无一的武学奇才,我这有本<图片流>秘籍,见与你有缘,就送于你了. 图片流 本文所说的图片流就是读取本地图片,并在页面使用文件流的方式显示出来. 首先,我们简单说 ...

  7. 面试官留步!听我跟你侃会儿Docker原理

    1 Docker 简介 1.1 Docker 由来 Docker 是基于 Go 语言开发的一个容器引擎,Docker是应用程序与系统之间的隔离层.通常应用程序对安装的系统环境会有各种严格要求,当服务器 ...

  8. 怎么把动态图从python弄下来_发一只我一直在用的爬虫——爬取“解闷”动态图的爬虫,绅士不妨留步^=^...

    马上注册,结交更多好友,享用更多功能^_^ 您需要 登录 才可以下载或查看,没有帐号?立即注册 x 本帖最后由 疾风.意破天晴 于 2018-5-27 13:56 编辑 因为GIF这种东西似乎从诞生到 ...

  9. 【S操作】老铁留步,干货来了!小总结云存储云办公云笔记工具——我的云工具选择,供您参考...

    公众号关注 "DLGG创客DIY" 设为"星标",重磅干货,第一时间送达. 之前总结过云办公软件的分类: [工具]更新云文档办公利器汇总,腾讯文档测试文件上传, ...

最新文章

  1. Java:Java 队列的遍历
  2. 第一章:OpenCV入门
  3. 基于diff的文件同步算法(上)
  4. Chapter5_Speaker_Verification
  5. qc35 说明书_使用Bose QC35 2年的心得 | 迟而不迟的深度体验 | 文附佩戴效果照片...
  6. 好程序员前端教程之JavaScript闭包和匿名函数的关系详解...
  7. PHP正则表达式提取超链接及其标题
  8. Sort方法根据T类某个字段对泛型集合ListT排序
  9. 创建一个delete触发器_基于 Django 信号机制实现类似触发器的效果
  10. Mybatis-plus插入数据遇到主键没有默认值的问题
  11. 使用Python编写Prometheus监控metrics接口
  12. linux python mysqldb安装包,linux环境下python中MySQLdb模块的安装方法
  13. 卫生纸玫瑰花折法5步_手工教程:做一个漂亮的玫瑰花捧花,用折纸表达我喜欢你...
  14. 计算机无法连接因特网络,有网但是无法连接到internet
  15. 名帖119 文徵明 小楷《摩诃般若波罗蜜多心经》
  16. 电脑耳机拔出后,再插入没声音
  17. iOS基础 UIWindow
  18. 昨天,我的大学学习[5]--转载自:www.cstc.net.cn
  19. Nanopi r4s usb网卡设置方法(MT7601U Wireless Adapter)
  20. 【Paper】DTWSequence Analysis

热门文章

  1. 安卓无法使用图片,报错Resource emoticon is not a Drawable
  2. JDK是什么?jre和jdk的区别?【JDK常见问题答疑】
  3. Source Insight 4.0 快捷键设置多行注释与反注释
  4. 下载量最高 100 个 Laravel 扩展包推荐
  5. js Number parseInt()
  6. 【Get深一度】寄生参数/密勒效应
  7. html5 3D旋转木马幻灯片播放
  8. Python入门学习——程序设计基本方法
  9. ETag助力站点提交sitemap,对站点服务器如何配置ETag
  10. 发布买家助手(淘宝搜索)1.0