JS 中 Array.reduce() 的使用方法

65 阅读2分钟

1.语法

arr.reduce(callbackFn, [initialValue])

reduce() 方法会对数组中的每个元素按顺序执行你提供的回调函数。

callbackFn 回调函数中,可以接受四个参数:

  • previousValue:上一次调用 callbackFn 时的返回值。在第一次调用时,并没有执行过回调函数,所以没有返回值,如果你指定了初始值 initialValue,那么这个值就会作为第一次调用时的返回值;否则的话就会把数组的第一项 arr[0] 当作第一次调用时的返回值。
  • currentValue:数组中正在处理的元素。
  • currentIndexcurrentValue 的索引值。
  • array:用于遍历的数组。

2.[initialValue]传与不传的区别

首先来看不传:

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

const sumWithoutInitial = arr.reduce((pre, cur, index, arr) => {
    console.log(pre, cur, index, arr)
    return pre + cur
})
console.log(sumWithoutInitial)

// 打印结果
1 2 1 [1, 2, 3, 4]
3 3 2 [1, 2, 3, 4]
6 4 3 [1, 2, 3, 4]
10

从打印结果我们可以看出来,index 是从 索引1 开始的,arr[0] 被当作了第一次调用时 pre 的值。

再来看传:

const arr = [1, 2, 3, 4]
const initialValue = 0

const sumWithInitial = arr.reduce((pre, cur, index, arr) => {
    console.log(pre, cur, index, arr)
    return pre + cur
}, initialValue)
console.log(sumWithInitial)

// 打印结果
0 1 0 [1, 2, 3, 4]
1 2 1 [1, 2, 3, 4]
3 3 2 [1, 2, 3, 4]
6 4 3 [1, 2, 3, 4]
10

这次 index 是从 索引0 开始的, 第一次调用时 pre 的值是 initialValue

所以,作为第一次调用 callback 函数时,若指定了初始值 initialValue,则 currentValue 则将使用数组第一个元素;否则 previousValue 将使用数组第一个元素,而 currentValue 将使用数组第二个元素。

3.常见用法

(1)计算数组中各元素出现的次数

const items = [3, 2, 2, 8, 1, 5, 8]

const itemNum = items.reduce((pre, cur) => {
    if (pre[cur]) {
        pre[cur]++
    } else {
        pre[cur] = 1
    }
    return pre
}, {})

console.log(itemNum)
// {1: 1, 2: 2, 3: 1, 5: 1, 8: 2}

// 也可以简写:
const itemNum = items.reduce((pre, cur) => (pre[cur]++ || (pre[cur] = 1), pre), {})

(2)求数组所有值的和

const sum = [0, 1, 2, 3].reduce((pre, cur) => pre + cur, 0)
console.log(sum) // 6

(3)累加对象数组里的值

const sum = [{x: 1}, {x: 2}, {x: 3}].reduce((pre, cur) => pre + cur.x, 0)
console.log(sum) // logs 6

(4)将二维数组转为一维

const flattened = [[0, 1], [2, 3], [4, 5]].reduce((pre, cur) => pre.concat(cur), [])
console.log(flattened) // [0, 1, 2, 3, 4, 5]

(5)数组去重

const myArray = ['a', 'b', 'a', 'b', 'c', 'e', 'e', 'c', 'd', 'd', 'd', 'd']
const myArrayWithNoDuplicates = myArray.reduce((pre, cur) => {
  if (pre.indexOf(cur) === -1) {
    pre.push(cur)
  }
  return pre
}, [])

console.log(myArrayWithNoDuplicates) // ['a', 'b', 'c', 'e', 'd']