JavaScript reduce()方法详解与实现

  • Post author:
  • Post category:java




使用方法详解

reduce()方法在数组的每个元素上依次执行传入的‘reducer’回调函数,并传入上一次计算的返回值。第一次运行回调函数的时候没有‘上一次计算的返回值’。调用reduce()方法的时候可以传一个初始值来代替,否则,数组的第一个元素将被用作初始值,迭代从索引为1的元素开始。先看一个最简单的累加:

const array1 = [1, 2, 3, 4];

// 0 + 1 + 2 + 3 + 4
const initialValue = 0;
const sumWithInitial = array1.reduce(
  (previousValue, currentValue) => previousValue + currentValue,
  initialValue
);

console.log(sumWithInitial);
// expected output: 10

上述例子中,传给reduce()方法的回调函数,有两个参数previousValue,currentValue。这是最普遍的情况,实际上这个回调函数可以传入四个参数:

reduce(function(previousValue, currentValue, currentIndex, array) { /* … */ })
  • previousValue

    从命名就能看出来,这个参数代表上一次调用回调函数产生的值。第一次调用时,除非指定了initialValue,否则就是数组索引为0的值
  • currentValue

    当前元素的值,第一次调用时如果指定了initialValue,就为数组索引0的值,否则就为数组索引为1的值。
  • currentIndex

    当前元素的索引,第一次调用时如果指定了initialValue,就为0,否则为1
  • array

    正在遍历的数组

reduce()方法的第一个参数是上述的回调函数,还有第二个可选参数,就是initialValue,也就是在第一次调用回调函数时作为previousValue的值。

reduce()方法的返回值就是数组的最后一个元素运行回调函数完毕后的最终结果。


值得注意的点:

  1. 如果在reduce()开始遍历数组之后往数组里添加元素,回调函数不会遍历后加的元素
  2. 如果数组现有元素发生更改,传递给回调函数的值是reduce()第一次在数组上调用时的值
  3. reduce()调用后,开始遍历前删除的元素不会被reduce()访问


如果要计算对象数组中包含的值,必须提供一个初始值,以便函数遍历到每个元素,比如:

const objects = [{ x: 1 }, { x: 2 }, { x: 3 }];
const sum = objects.reduce(
  (previousValue, currentValue) => previousValue + currentValue.x,
  0,
);

console.log(sum); // 6



实现

Array.prototype.myReduce = function (callback) {
    // 获取初始值,如果有初始值,那就是第二个参数
    const initVal = arguments[1] ? arguments[1] : "";
    // 此处的this指向调用reduce的数组
    const len = this.length;
    // 没有初始值并且数组为空,报错
    if( !len && !initVal ) {
        throw Error('Reduce of empty array with no initial value');
    }
    // 数组为空,直接返回初始值
    if( !len )  return initVal;
    // 上次返回值,没初始值就是数组第一个元素
    let previousValue = initVal ? initVal : this[0];
    let currentIndex = initVal ? 0 : 1;
    for ( ; currentIndex < len; currentIndex++ ) {
        previousValue = callback(previousValue , this[currentIndex], currentIndex, this); // 每次执行回调返回的值赋值给total
    }
    return previousValue ;
}



版权声明:本文为qq_45643079原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。