这是一篇多年前写的博文,今日再读,发现写得还可以,分享给大家
因为用for循环被老大鄙视之后,这几天都在偷偷摸摸的研究数组的那几个迭代方法。
使用下来,感觉确实妙用无穷,仿佛自己的逼格在无形中变得高大了一点点,哈哈,上一篇文章的简单介绍确实有点糙,因此决定重新一些总结文章。这篇文章就是专门总结reduce方法的,这个方法大有可研究的地方,值得大家get它并去动手实践一下。
上一篇文章我认为reduce是一个聚合或者减少方法,它可以将数组中的每一项通过叠加变成一项,但是其实这种说法似乎不太准确。先不管这个,我们来看看例子再说。
从最简单的例子开始。
var arr = [1, 2, 3, 4, 5];sum = arr.reduce(function(prev, cur, index, arr) { console.log(prevres, cur, index); return prevres + cur;})console.log(arr, sum);
输出结果
1 2 13 3 26 4 310 5 4[1, 2, 3, 4, 5] 15
回顾一下reduce中回调函数的参数,这个回调函数有4个参数,意思分别为
1.prev: 第一项的值或上一次叠加的结果值2.cur: 当前会参与叠加的项3.index:当前值的索引4.arr: 数组本身
首先我们要弄明白prev与cur这2个参数的区别,刚开始我以为他们是一种类型的,可是后来我发现我理解错了。prev表示每次叠加之后的结果,类型可能与数组中的每一项不同,而cur则表示数组中参与叠加的当前项。在后边我们可以结合实例来理解这个地方。
其次我们看到,上例中其实值遍历了4次,数组有五项。数组中的第一项被当做了prev的初始值,而遍历从第二项开始。
我们看下面一个例子。
某同学的期末成绩如下表示
var result = [ { subject: 'math', score: 88 }, { subject: 'chinese', score: 95 }, { subject: 'english', score: 80 }];
如何求该同学的总成绩?
很显然,利用for循环可以很简单得出结论
var sum = 0;for(var i=0; i sum += result[i].score;}
但是我们的宗旨就是抛弃for循环,因此使用reduce来搞定这个问题
var sum = result.reduce(function(prev, cur) { return cur.score + prev;}, 0);
这个时候,我给reduce参数添加了第二个参数。通过打印我发现设置了这个参数之后,reduce遍历便已经从第一项开始了。
这第二个参数就是设置prev的初始类型和初始值,比如为0,就表示prev的初始值为number类型,值为0,因此,reduce的最终结果也会是number类型。
因为第二个参数为累计结果的初始值,因此假设该同学因为违纪被处罚在总成绩上扣10分,只需要将初始值设置为-10即可。
var sum = result.reduce(function(prev, cur) { return cur.score + prev;}, -10);
来给这个例子增加一点难度。假如该同学的总成绩中,各科所占的比重不同,分别为50%,30%,20%,我们应该如何求出最终的权重结果呢?
解决方案如下:
var dis = { math: 0.5, chinese: 0.3, english: 0.2}var sum = result.reduce(function(prev, cur) { return cur.score + prev;}, -10);var qsum = result.reduce(function(prev, cur) { return prev + cur.score * dis[cur.subject]}, 0)console.log(sum, qsum);
为了计算出权重之后的总值,我们在回调函数内部修改了数组当前项,是使他和权重比例关联袭来,并重新返回一个一样的回调函数,将新修改的当前项传入,就和之前的例子是一样的了。
在segmentfault上看到一个面试题,问如何知道一串字符串中每个字母出现的次数?
可以运用reduce来解决这个问题。
如下代码,我在reduce的第二个参数里面初始了回调函数第一个参数的类型和值,将字符串转化为数组,那么迭代的结果将是一个对象,对象的每一项key值就是字符串的字母。运行感受一下吧。
var arrString = 'abcdaabc';arrString.split('').reduce(function(res, cur) { res[cur] ? res[cur] ++ : res[cur] = 1 return res;}, {})
由于可以通过第二参数设置叠加结果的类型初始值,因此这个时候reduce就不再仅仅只是做一个加法了,我们可以灵活的运用它来进行各种各样的类型转换,比如将数组按照一定规则转换为对象,也可以将一种形式的数组转换为另一种形式的数组,大家可以动手去尝试一样。
[1, 2].reduce(function(res, cur) { res.push(cur + 1); return res; }, [])
这种特性使得reduce在实际开发中大有可为!但是需要注意点,在ie9一下的浏览器中,并不支持该方法 !
【面经分享】好未来-北京-视频面试
大厂面试过程复盘(微信/阿里/头条,附答案篇)
前端面试高频手写代码题
58道Vue常见面试题集锦,涵盖入门到精通,自测 Vue 掌握程度
前端面试128问汇总(含超详细答案)
15道TypeScript练习题 [中篇]
如何和面试官吹嘘一下我的Vue项目性能优化「面试必问」leetcode高频题精选
经常需要谷哥的ccs问题完美方案汇总
前端的你该如何学习算法?【面试准备】每日前端面试题 - 55(百度面试题)【面试准备】每日前端面试题 - 54(字节面试题) 【面试准备】每日前端面试题 - 53(字节面试题)【面试准备】每日前端面试题 - 52(动态规划算法题)
【面试准备】每日前端面试题 - 51 (字节面试题)
【面试准备】每日前端面试题 - 50 (字节面试题)
【面试准备】每日前端面试题 - 49 (字节面试题)
【面试准备】每日前端面试题 - 48 (美团校招面试)
【面试准备】每日前端面试题 - 47 (校招滴滴面试)
移动端1px问题应该如何解决?
为什么我们要熟悉这些通信协议?【精读】
前端面向对象,高阶JS应用!
面试前必读!!!原生JS补给(上)
前端p6笔试题,你可以答上多少个?
每天都在用class,你到底对它了解多小?
前端工程师必须掌握的几个JavaScript设计模式及场景应用
【JS进阶深挖】完全弄懂数据类型转换(下)
【收藏系列】JS灵魂之问(下) - 附个人成长经验分享
【收藏系列】JS灵魂之问, 是否有offer看你接到多少个(中)
【收藏系列】JS灵魂之问, 请问你能接得住几个?(上)
【大厂面试】20道超高频题目 【JS进阶深挖】完全弄懂数据类型转换(上) 前端架构师最终面试题!48道题JS继承题目【面试官再也难不倒你了系列】神奇的arguments笔试题【一天突破一个知识点】45道Promise面试题【面试官再也难不倒你了系列】40道this面试题!面试官再也难不到你了!![1d925832af083807bb9bd2cc041f1f00.png](https://i-blog.csdnimg.cn/blog_migrate/01a5f07bd04efe9369010b6d11ffb0f1.png)
![e891e953c7c27f552a623c0190164fd3.gif](https://i-blog.csdnimg.cn/blog_migrate/81a78ded23a80843f50bebbc4ea41fe7.gif)