手写一个array.reduce()方法

2,079 阅读2分钟

这是我参与8月更文挑战的第5天,活动详情查看:8月更文挑战

theme: juejin

问题

手写实现一个array.reduce();

需要实现的目标: 在原型链上实现reduce, 可直接被调用,例如array.myReduce();

了解array.reduce()

接收两个参数,一个处理数据的函数,一个为初始值。

接收的处理数据的函数,可接收四个参数(total,curValue,curIndex,array);

  • total (上一次调用回调返回的值,或者是提供的初始值(initialValue))
  • curValue (数组中当前被处理的元素)
  • curIndex (当前元素在数组中的索引)
  • array (调用 reduce 的数组)

手动实现

定义一个函数 myfunction(callback,initialValue);

当this或者callback 不为正确语法时,抛出错误; this指向调用reduce的数组

把调用的值通过Object(this)包装成一个类对象。如同以下,this指向1212也可以被执行,因为Object(1212) 转变成了Number {1212}

Array.prototype.reduce.call(1212,(pre,cur)=>{return ''+pre+cur},0)
0

把手写的myyReduce 写入到Array 的原型链上 Array.prototype.MyReduce = MyReduce;

function MyReduce(fun, initValue) {
  if (this === null) {
      // this 不存在,抛出错误
        throw new TypeError( 'Array.prototype.reduce ' +
          'called on null or undefined' );
      }
      if (typeof fun !== 'function') {
      // fun 不是function时,抛出错误
        throw new TypeError( fun +
          ' is not a function');
      }
      const value = Object(this);
      let preValue, curValue, curIndex;
  if (initValue !== undefined) {
    preValue = initValue;
    curValue = arr[0];
    curIndex = 0;
  } else {
    preValue = arr[0];
    curValue = arr[1];
    curIndex = 1
  }
   for (let i = curIndex; i < value.length; i++) {
      const item = value[i];
      preValue = fun(preValue, item, i, arr);
    }
  return preValue;
}

function setReduce(preValue, curValue, index, arr) {
  return `${preValue} - ${curValue}`;
}
// 把方法写入到原型链上
Array.prototype.MyReduce = MyReduce;

测试

通过定义一个数组,直接调用测试

const arr1=[1, 2, 3, 4, 5]
let num = arr1.MyReduce(setReduce);
console.log(num); // 15 

总结:

reduce() 是数组的归并方法,与forEach()、map()、filter()等迭代方法一样都会对数组每一项进行遍历。

reduce() 可同时将前面数组项遍历产生的结果与当前遍历项进行运算,这一点是其他迭代方法无法企及的。

reduce() 可以作为一个高阶函数,用于函数的 compose。如何手动实现一个compose,可以通过聊聊redux里compose函数来了解。