由于用for循环被老大鄙视以后,这几天都在偷偷摸摸的研究数组的那几个迭代方法。使用下来,感受确实妙用无穷,仿佛本身的逼格在无形中变得高大了一点点,哈哈,上一篇文章的简单介绍确实有点糙,所以决定从新一些总结文章。面试
这篇文章就是专门总结reduce方法的,这个方法大有可研究的地方,值得你们get它并去同手实践一下。segmentfault
上一篇文章我认为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 1 3 3 2 6 4 3 10 5 4 [1, 2, 3, 4, 5] 15
咱们先从新回顾一下reduce中回调函数的参数,这个回调函数中有4个参数,意思分别为spa
prev: 第一项的值或者上一次叠加的结果值
cur: 当前会参与叠加的项
index: 当前值的索引
arr: 数组自己code
首先咱们要区分prev与cur这2个参数的区别,刚开始的时候我觉得他们是一种类型的,但是后来我发现我理解错了。prev表示每次叠加以后的结果,类型可能与数组中的每一项不一样,而cur则表示数组中参与叠加的当前项。在后边咱们能够结合实例来理解这个地方。对象
其次咱们看到,上例中其实值遍历了4次,数组有五项。数组中的第一项被当作了prev的初始值,而遍历从第二项开始。索引
咱们看下面一个例子。ip
某同窗的期末成绩以下表示
var result = [ { subject: 'math', score: 88 }, { subject: 'chinese', score: 95 }, { subject: 'english', score: 80 } ];
如何求该同窗的总成绩?
很显然,利用for循环能够很简单得出结论
var sum = 0; for(var i=0; i<result.length; 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) { console.log(prev); 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一下的浏览器中,并不支持该方法 !