深入解析rudece

127 阅读3分钟

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,方便大家理解

  1. 首先 reduce会接收两个参数回调函数fn和初始值prev
  2. 但是prev可能会传,也可能不传,所以在这里要判断prev是不是undefined
  3. 当prev它为undefined时,回调函数fn接收的四个值分别为:this[i],this[i+1],i+1,this。此时的this就是被循环的数组。要特别注意currentIndex 即 i 的赋值,在执行完prev的赋值后要给i+1,以确保下次取值是正确的,此处的理解可参考上面对currentIndex的解析。
  4. 当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]
})