帮你精通JS:神奇的array.reduce方法的10个案例

当接触到reduce方法之后,仿佛从金庸的山洞中学会了旷世武功,读着 manual 久久不愿意翻页 。
一、array.reduce 方法概览reduce() 方法对数组中的每个元素执行一个由您提供的reducer函数(升序执行),将其结果汇总为单个返回值 。
const array1 = [1, 2, 3, 4];const reducer = (accumulator, currentValue) => accumulator + currentValue;// 1 + 2 + 3 + 4console.log(array1.reduce(reducer));// expected output: 10// 5 + 1 + 2 + 3 + 4console.log(array1.reduce(reducer, 5));// expected output: 15reducer 函数接收4个参数:

  1. Accumulator (acc) (累计器)
  2. Current Value (cur) (当前值)
  3. Current Index (idx) (当前索引)
  4. Source Array (src) (源数组)
您的 reducer 函数的返回值分配给累计器,该返回值在数组的每个迭代中被记住,并最后成为最终的单个结果值 。
二、array.reduce 的语法arr.reduce(callback( accumulator, currentValue, [, index[, array]] )[, initialValue])参数
  • callback
    执行数组中每个值 (如果没有提供 initialValue则第一个值除外)的函数,包含四个参数:- accumulator 累计器累计回调的返回值; 它是上一次调用回调时返回的累积值,或initialValue(见于下方) 。
    - currentValue 数组中正在处理的元素 。 - index 可选 数组中正在处理的当前元素的索引 。如果提供了initialValue,则起始索引号为0,否则从索引1起始 。 - array可选 调用reduce()的数组
  • initialValue可选
    作为第一次调用 callback函数时的第一个参数的值 。如果没有提供初始值,则将使用数组中的第一个元素 。在没有初始值的空数组上调用 reduce 将报错 。
返回值
函数累计处理的结果
三、描述reduce为数组中的每一个元素依次执行callback函数,不包括数组中被删除或从未被赋值的元素,接受四个参数:
  • accumulator 累计器
  • currentValue 当前值
  • currentIndex 当前索引
  • array 数组
回调函数第一次执行时,accumulator 和currentValue的取值有两种情况:如果调用reduce()时提供了initialValue,accumulator取值为initialValue,currentValue取数组中的第一个值;如果没有提供 initialValue,那么accumulator取数组中的第一个值,currentValue取数组中的第二个值 。
注意:如果没有提供initialValue,reduce 会从索引1的地方开始执行 callback 方法,跳过第一个索引 。如果提供initialValue,从索引0开始 。
如果数组为空且没有提供initialValue,会抛出TypeError。如果数组仅有一个元素(无论位置如何)并且没有提供initialValue,或者有提供initialValue但是数组为空,那么此唯一值将被返回并且callback不会被执行 。
提供初始值通常更安全,正如下面的例子,如果没有提供initialValue,则可能有四种输出:
var maxCallback = ( acc, cur ) => Math.max( acc.x, cur.x );var maxCallback2 = ( max, cur ) => Math.max( max, cur );// reduce() 没有初始值[ { x: 2 }, { x: 22 }, { x: 42 } ].reduce( maxCallback ); // NaN[ { x: 2 }, { x: 22 }].reduce( maxCallback ); // 22[ { x: 2 }].reduce( maxCallback ); // { x: 2 }[].reduce( maxCallback ); // TypeError// map/reduce; 这是更好的方案,即使传入空数组或更大数组也可正常执行[ { x: 22 }, { x: 42 } ].map( el => el.x ).reduce( maxCallback2, -Infinity );四、array.reduce 如何运行?假如运行下段reduce()代码:
[0, 1, 2, 3, 4].reduce(function(accumulator, currentValue, currentIndex, array){return accumulator + currentValue;});callback 被调用四次,每次调用的参数和返回值如下表:
callback
accumulator
currentValue
currentIndex
array
return value
first call
0
1
1
[0, 1, 2, 3, 4]
1
second call
1
2
2
[0, 1, 2, 3, 4]
3
third call
3
3
3
[0, 1, 2, 3, 4]
6
fourth call
6
4
4
[0, 1, 2, 3, 4]
10
由reduce返回的值将是最后一次回调返回值(10) 。
你还可以使用箭头函数来代替完整的函数 。下面的代码将产生与上面的代码相同的输出:
[0, 1, 2, 3, 4].reduce((prev, curr) => prev + curr );如果你打算提供一个初始值作为reduce()方法的第二个参数,以下是运行过程及结果:
[0, 1, 2, 3, 4].reduce((accumulator, currentValue, currentIndex, array) => {return accumulator + currentValue}, 10)


推荐阅读