reduce的用法:
reduce() 方法接收一个函数作为累加器,数组中的每个值(从左到右)开始缩减,最终计算为一个值, 可用于数组的收敛或叠加。
注意: reduce() 对于空数组是不会执行回调函数的。
2. reduce的参数:
reduce的参数有两个,回调函数function(prev,next,currentIndex,array)和initialValue。
回调函数传递的四个参数:
- prev:必需。初始值, 或者计算结束后的返回值。
- next:必需。当前元素。
- currentIndex:可选。当前元素索引。
- array:可选。当前元素所属的数组对象即此时被循环的数组
用reduce求和,它返回的结果是叠加后的结果
下面用一个例子深入理解参数prev和currentIndex:
当没有传递initialValue时
let total = [1,2,3,4,5].reduce((prev,next,currentIndex,array)=>{
return prev+next;
})
以上代码会循环四次,并且函数的返回结果会作为下一次循环是的prev
第一次进入循环时,prev = 1,next= 2,currentIndex = 1,
第二次进入循环时,prev = 3(上一次计算的加和),next 为3,currentIndex = 2,
第三次进入循环时,prev = 6(上一次计算的加和),next 为4,currentIndex = 3,
第四次进入循环时,prev = 10(上一次计算的加和),next 为5,currentIndex = 4,此时循环结束,返回15
当传了initialValue = 0时
let total = [1,2,3,4,5].reduce((prev,next,currentIndex,array)=>{
return prev+next;
},0)
此时代码会循环五次:
第一次进入循环时,prev = 0,next= 1,currentIndex = 0,
第二次进入循环时,prev = 1(上一次计算的加和),next= 2,currentIndex = 1,
第三次进入循环时,prev = 3(上一次计算的加和),next 为3,currentIndex = 2,
第四次进入循环时,prev = 6(上一次计算的加和),next 为4,currentIndex = 3,
第五次进入循环时,prev = 10(上一次计算的加和),next 为5,currentIndex = 4,此时循环结束,返回15。
当然initialValue一般不是这么用的,当被循环数组的每一项是一个对象时,可以给它传递一个initialValue便于后续的计算,下面的代码更贴切的展示了initialValue的用法:
let total = [{price:10},{price:20},{price:10}].reduce((prev,next,currentIndex,array)=>{
return prev+next.price;
},0)
3. reduce的原理
下面我们将手写reduce,方便大家理解
- 首先 reduce会接收两个参数回调函数fn和初始值prev
- 但是prev可能会传,也可能不传,所以在这里要判断prev是不是undefined
- 当prev它为undefined时,回调函数fn接收的四个值分别为:this[i],this[i+1],i+1,this。此时的this就是被循环的数组。要特别注意currentIndex 即 i 的赋值,在执行完prev的赋值后要给i+1,以确保下次取值是正确的,此处的理解可参考上面对currentIndex的解析。
- 当prev不是undefined时,,回调函数fn接收的四个值分别为:上一次计算的结果prev,this[i],i,this。
具体代码如下:
Array.prototype.reduce = function(fn,prev){
for(let i=0;i<this.length;i++){
if(typeof prev === 'undefined'){
prev = fn(this[i],this[i+1],i+1,this);
++i;
}else{
prev = fn(prev,this[i],i,this)
}
}
return prev
}
let total = [1,2,3].reduce((prev,next,currentIndex,ary)=>{
return prev+next;
})
console.log(total)
4.reduce的其他用法
数组的拍平
let flat = [[1,2,3],[4,5,6]].reduce((prev,next,index,arr)=>{
return [...prev,...next]
})