JS手写 reduce

2,341 阅读1分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第21天,点击查看活动详情

前言

个人认为 reduce() 方法是 Array.pototype 上所有高阶函数中,功能最为强大,抛去性能之间的区别, 其他的高阶函数能实现的功能,它都可以做到,而它能做到,其他高阶函数不一定能够做到。

如果能够手写实现了 reduce ,基本都可以实现 Array.pototype 的其他高阶函数。

实现的基本思路

reduce 的本质还是遍历数组,不过是每次遍历都调用传入的回调函数 callback ,然后保存 callback 的返回值,作为下一次执行 callback 的参数,直到数组遍历完成。

代码

首先定义方法,包括它的参数和返回值。

主要接受两个参数:一个是每次遍历元素执行的回调函数 callback;一个是上一次的执行结果 preValue,这个参数是可选的。

返回值就是返回最终的 preValue,代码如下:

/**
 * 手写reduce
 * @param { Function } callback 处理函数
 * @param { any } preValue 上一次返回结果
 * @returns { any }
 */
Array.prototype.myReduce = function (callback, preValue) {
  return preValue
}

然后就是参数检测,callback 必须是函数,而 preValue 可以是任何值,不许检测,代码如下:

  if (typeof callback !== 'function') {
    throw new Error(`${callback} is not a function !`)
  }

接着就是对 preValue 进行处理,如果使用 reduce 时没有传入第二个参数,则 preValue 默认是数组的第一个元素,第一次遍历是从数组的第二个元素开始,代码如下:

  // 当前遍历索引
  let index = 0
  // 数组长度
  let len = this.length
  // 如果 preValue 没有传入,当前索引变更为 1,preValue 变更为 数组的第一个元素
  if (preValue === undefined) {
    index = 1
    preValue = this[0]
  }

接下来就是遍历数组,步骤如下:

    1. 每遍历一个元素,执行一次回调函数 callback
    1. 回调函数 callback,传入四个参数:上一次的返回值、当前元素、当前索引、被遍历的数组;
    1. callback 的返回值作为下一次执行 callback 的参数
    1. 数组遍历完成,返回 preValue;

代码如下:

 // 逐层遍历
  for (; index < len; index++) {
    /**
     * 四个参数:
     * 上一次的返回值
     * 当前元素
     * 当前索引
     * 遍历的数组
     */
    preValue = callback(preValue, this[index], index, this)
  }
  return preValue

完整代码如下:

Array.prototype.myReduce = function (callback, preValue) {
  if (typeof callback !== 'function') {
    throw new Error(`${callback} is not a function !`)
  }

  let index = 0
  let len = this.length
  if (preValue === undefined || preValue === null) {
    index = 1
    preValue = this[0]
  }

  for (; index < len; index++) {
    preValue = callback(preValue, this[index], index, this)
  }
  return preValue
}

和原生的 reduce 同时执行,简单测试一下:

const arr = [1, 2, 3, 4, 5, 6]

console.log('Array.prototype.reduce 1:', arr.reduce((a, b) => a + b))
console.log('Array.prototype.reduce 2:', arr.reduce((a, b) => a + b, ''))

console.log('my reduce 1:', arr.myReduce((a, b) => a + b))
console.log('my reduce 2:', arr.myReduce((a, b) => a + b, ''))

微信截图_20221028171744.png

至此,基本完成了。