JS基础 Reduce详解

4,064 阅读2分钟

reduce()

reduce 方法对数组的每个元素执行提供的reducer函数,将结果汇为单个返回值。

使用

arr.reduce(callback(accumulator, currentValue, index, array), initialValue)

reducer

callback 执行数组中每个值的函数,包括四个参数。

accumulator

累计,累计回调的返回值。上一次回调返回的累计值。 问题,累计值的初始值时如何选取的?

currentValue 当前值数组中正在处理的元素

index

索引,当前正在处理数组的索引值。如果提供了initialValue,索引号为0,否则索引从1开始。提供了初始值,迭代次数为arr.length,未提供初始值,迭代次数为arr.length - 1。第一次回调把数组第一个元素作为累加初始值,并从索引为1的元素开始迭代。

array 调用reduce()的函数。

initialValue 初始值

1、如果提供了初始值,将作为第一次调用callback函数时的第一个参数值(ACCUMULATOR)的值。 2、如果没有提供初始值,则把数组第一个值作为callback第一个参数的值。 注意点就是是否将初始值作为第一次调用callback函数的累加值。

应用

数组累加

数据累加,设置初始值,初始值。

let sum = [1, 2, 3, 5].reduce((acc, current) => {
 return acc + current 
}, 0)

对象属性和

let sum = [{x: 1}, {x: 3}, {x: 5}, {x: 6}].reduce((acc, current) => {
  return acc + current.x
}, 0)

Promise 队列

let promiseFn = function () {
    return new Promise((resolve, reject) => {
      setTimeout(() => {
        console.log('resolve1')
        resolve()
      }, 1000)
    })
  }
  let promiseFn2 = function () {
    return new Promise((resolve, reject) => {
      setTimeout(() => {
        console.log('resolve2')
        resolve()
      }, 1000)
    })
  }
  let promiseFn3 = function () {
    return new Promise((resolve, reject) => {
      setTimeout(() => {
        console.log('resolve3')
        resolve('last resolve')
      }, 1000)
    })
  }
  let pro = [promiseFn, promiseFn2, promiseFn3].reduce((p, f) => {
    return p.then(f)
  }, Promise.resolve()) // 提供initialValue,从第一个参数遍历
  pro.then(res => {
    console.log('res', res)
  })

计算数组中每个元素出现的次数

需要注意的是需要提供一个初始值{}来承接每次循环的返回值

let names = ['alice', 'Bob', 'lee', 'mark']
let nameNum = names.reduce((acc, cur) => {
    if (!acc[cur]) {
        acc[cur] = 1
    } else {
        acc[cur]++
    }
    return acc
}, {})

数组去重

let arr = ['1', '2', '2', '3', '4'].reduce((acc, cur) => {
  if (!acc.includes[cur]) {
    return acc.concat(cur)
  }
  return acc
}, [])
// 当然还可以使用new set 
// Array.from 从一个类似数组或可迭代对象创建一个新的,浅拷贝的数组实例。
Array.from(new Set(myArray))

二维数组转行成一维数组

let arr = [['1', '2'], ['3', '4']].reduce((acc, cur) => {
  return acc.concat(cur)
}, [])

多维数组转换成一维数组

采用递归的思路处理

let arr1 = [[0, 1], [2, 3], [4, [5, 6, 7]]]
const flattenArr = function (arr) {
  return arr.reduce((acc, cur) => {
    return acc.concat(Array.isArray(cur) ? flattenArr(cur) : cur)
  }, [])
}
console.log(flattenArr(arr1))

总结

reduce的参数为callback、initialValue,callback具有四个参数。第一个参数accumulator累计值,currentValue、index,arr。当设置了初始值,index从0开始,且作为第一次回调的accumulator的初始值。当未提供initialValue时,index从1开始,且数组第一个参数作为第一次回调的累计值初始值,迭代次数也少一次。 借助reduce可以很方便的实现promise异步链、扁平化数组、数组去重、求和等。