# 了解一下 reduce?
# 作用
reduce() 方法对数组中的每个元素执行一个由您提供的reducer函数(升序执行),将其结果汇总为单个返回值。
# 语法
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(opens new window)(无论位置如何)并且没有提供initialValue, 或者有提供initialValue但是数组为空,那么此唯一值将被返回并且callback不会被执行。
# 手写
Array.prototype._reduce = function(callback, initialValue) {
  let first = true
  let array = this
  let accumulator, currentValue, index
  if (array.length === 0 && initialValue === void 0) {
    // 数组为空且没有提供initialValue,会抛出TypeError
    throw new Error('TypeError')
  }
  if (array.length === 1 && initialValue === void 0) {
    // 数组仅有一个元素(无论位置如何)并且没有提供initialValue
    return array[0]
  }
  if (array.length === 0 && initialValue !== void 0) {
    // 有提供initialValue但是数组为空
    return initialValue
  }
  return (() => {
    for (let i = 0, j = array.length; i < j; i++) {
      if (first) {
        // 第一次执行
        first = false
        if (initialValue !== void 0) {
          // 如果调用reduce()时提供了initialValue,accumulator取值为initialValue,currentValue取数组中的第一个值
          accumulator = initialValue
          currentValue = array[0]
          // 如果提供initialValue,从索引0开始。
          // 注意:下一次索引应该是array[1]
          index = 0
        } else {
          // 如果没有提供 initialValue,那么accumulator取数组中的第一个值,currentValue取数组中的第二个值
          accumulator = array[0]
          currentValue = array[1]
          // 如果没有提供initialValue,reduce 会从索引1的地方开始执行 callback 方法,跳过第一个索引
          // 注意:下一次索引应该是array[2]
          index = 1
          i += 1
        }
      } else {
        currentValue = array[i]
        index = i
      }
      accumulator = callback(accumulator, currentValue, index, array)
    }
    return accumulator
  })()
}
 2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46