手写reduce

在 JavaScript 中,reduce 方法用于对数组中的每个元素执行一个提供的函数,将其结果汇总为单个数值。下面是 reduce 方法的基本语法:

array.reduce(callback(accumulator, currentValue, currentIndex, array), initialValue)

callback 是一个函数,用来执行对数组中每个元素的处理,它可以接受四个参数:
○accumulator:累加器,累积回调的返回值;它是上一次调用回调时返回的累积值,或者是初始值(如果有)。
○currentValue:当前正在处理的数组元素。
○currentIndex:当前正在处理的数组元素的索引(可选)。
○array:调用 reduce 的数组(可选)。
●initialValue 是作为第一次调用 callback 函数时的第一个参数 accumulator 的初始值(可选)。

下面是一个简单的示例,演示了如何使用 reduce 方法来计算数组中所有元素的总和:

const numbers = [1, 2, 3, 4, 5];
const sum = numbers.reduce((accumulator, currentValue) => accumulator + currentValue, 0);
console.log(sum); // 输出 15

在这个示例中,我们使用 reduce 方法计算了 numbers 数组中所有元素的总和。初始值为 0,然后对数组中的每个元素依次执行累加操作,最终得到总和值。

需要注意的是,reduce 方法可以用于更复杂的累积操作,比如计算平均值、查找最大/最小值等。你可以根据具体的需求使用 reduce 方法来处理数组中的元素,并将它们汇总为一个值。


实现

Array.prototype.myReduce = function (callback, initialValue) {
    //首先检查回调函数是否是函数
    if (typeof callback !== 'function') {
        throw new TypeError('callback must be a function');
    }
    // 检查数组是否为空,并设置累加器和起始索引  
    let accumulator = initialValue;
    let startIndex = 0;
    if (accumulator === undefined) {
        //如果是空数组且没有初始值,抛出异常
        if (this.length === 0) {
            throw new TypeError('Reduce of empty array with no initial value');
        }
        //如果数组不为空且没有初始值,则将累加器设置为数组的第一个元素,并设置起始索引为1,便于下面遍历
        accumulator = this[0];
        startIndex = 1;
    }
    for (let i = startIndex; i < this.length; i++) {
        accumulator = callback(accumulator, this[i], i, this)
    }
    // 返回累加器
    return accumulator;

}
//示例
const arr = [1, 2, 3, 4, 5];
const sum = arr.myReduce((accumulator, currentValue) => accumulator + currentValue, 0);
console.log(sum); // 输出 15
// 不使用初始值的情况  
const sumWithoutInitial = arr.myReduce((acc, cur) => acc + cur);  
console.log(sumWithoutInitial); // 输出 15


解释这段代码的逻辑。

首先,这段代码定义了一个自定义的 myReduce 方法,该方法被添加到 Array.prototype 上,这意味着所有的数组实例都可以使用这个方法。

这个 myReduce 方法模拟了 JavaScript 内置的 Array.prototype.reduce 方法的行为。它的目的是遍历数组,并将数组中的每个元素(从左到右)都通过一个回调函数进行转换,最终返回一个值。

下面是代码逻辑的详细解释:

  1. 参数:
    • callback: 这是一个函数,它接受四个参数:累加器(accumulator)、当前值(currentValue)、当前索引(currentIndex)和数组本身(array)。
    • initialValue: 可选参数,作为第一次调用 callback 函数时的第一个参数的值。如果没有提供此值,并且数组为空,则会抛出一个错误。
  1. 错误检查:
    • 首先,它检查 callback 是否是一个函数。如果不是,它会抛出一个 TypeError
    • 接着,它检查是否提供了 initialValue。如果没有提供,并且数组为空,它会抛出一个 TypeError,因为 reduce 在没有初始值且数组为空时不能正常工作。
  1. 初始化累加器和起始索引:
    • 如果提供了 initialValue,则累加器(accumulator)被设置为 initialValue,起始索引(startIndex)被设置为 0。
    • 如果没有提供 initialValue,但数组不为空,则累加器被设置为数组的第一个元素(this[0]),起始索引被设置为 1。
  1. 遍历数组:
    • 使用一个 for 循环从 startIndex 开始遍历数组,直到数组的末尾。
    • 在每次迭代中,它都会调用 callback 函数,并将累加器、当前值、当前索引和数组本身作为参数传递。
    • callback 函数的返回值被用作下一次迭代的累加器的值。
  1. 返回值:
    • 遍历完成后,myReduce 方法返回累加器的最终值。

在测试部分:

  • 第一个测试使用 myReduce 方法并提供了初始值 0。回调函数将累加器和当前值相加,因此最终返回了数组 [1, 2, 3, 4, 5] 的和,即 15。
  • 第二个测试没有提供初始值,因此 myReduce 方法使用数组的第一个元素(即 1)作为初始值,并继续累加。因此,它仍然返回 15。
const numbers = [1, 2, 3, 4, 5];  
  
const result = numbers.reduce((accumulator, currentValue, currentIndex, sourceArray) => {  
  // 在这里,你可以访问累加器(到目前为止的结果)  
  // 当前值(正在处理的数组元素)  
  // 当前索引(正在处理的元素的索引)  
  // 以及源数组(调用 reduce 的数组)  
  
  // 例如,我们可以创建一个对象数组,其中每个对象包含当前元素的值、索引和数组的长度  
  return [  
    ...accumulator, 
    // 将之前的累加器数组扩展(即添加之前的所有对象),
    // 不然就只是最后累加的结果[ { value: 5, index: 4, arrayLength: 5 } ]
    {  
      value: currentValue,  
      index: currentIndex,  
      arrayLength: sourceArray.length  
    }  
  ];  
}, [ ]); // 初始累加器值是一个空数组  
  
console.log(result);  
// 输出类似:[  
//   { value: 1, index: 0, arrayLength: 5 },  
//   { value: 2, index: 1, arrayLength: 5 },  
//   { value: 3, index: 2, arrayLength: 5 },  
//   { value: 4, index: 3, arrayLength: 5 },  
//   { value: 5, index: 4, arrayLength: 5 }  
// ]
  • 10
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

向画

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值