实现原生reduce方法

52 阅读1分钟

实现原生reduce方法

/**
 * @template T, U
 * @param {(previousValue: U, currentValue: T, currentIndex: number, array: T[]) => U} callbackFn
 * @param {U} [initialValue]
 * @return {Array<U>}
 */
Array.prototype.myReduce = function (callbackFn, initialValue) {
  if (typeof callbackFn !== 'function') {
    throw new TypeError('callbackFn is not function');
  }

  const arr = this;
  const len = arr.length;
  let startIndex = 0;
  let accumulator = initialValue;

  if (arguments.length < 2) {
    let found = false;
    let index = 0;

    while(index < len) {
      if (arr.hasOwnProperty(index)) {
        found = true;
        startIndex = index + 1;
        accumulator = arr[index];
        break;
      }
      index++;
    }
    if (!found) {
      throw new TypeError('empty array with no initialValue');
    }
  }

  for (let i=startIndex;i<len;i++) {
    if(arr.hasOwnProperty(i)) {
      accumulator = callbackFn(accumulator, arr[i], i, arr);
    }
  }
  return accumulator;
};

要点

  1. 当initialValue无值时,需要给定默认值,通常为arr[0];但arr[0]可能为empty,所以需要考虑稀疏数组的情况,且为防止arr[0]重复运算,startIndex应为1
  2. 需要考虑数组全为empty的情况

测试用例

const add = (acc, curr) => acc + curr
[1,2,3].myReduce(add) // 6
[,1,2,3].myReduce(add) // 6
[,,,].myReduce(add) // TypeError: empty array with no initialValue