基本概念
reduce()方法在数组中从左到右工作,为每一个元素依次执行回调函数(不包括数组中被删除或从未被赋值的元素)。
参数解析
使用语法: arr.reduce(callback,[initialValue])
- callback (执行数组中每个元素的函数,包含四个参数)
- previousValue (上一次调用回调返回的值,或者是提供的初始值(initialValue))
- currentValue (数组中当前被处理的元素)
- index (当前元素在数组中的索引)
- array (调用 reduce 的数组)
- initialValue (作为第一次调用 callback 的第一个参数。)
基础用法(示例)
未设置初始值情况
let arr = [2, 4, 6]
let sum = arr.reduce((prev, cur, index, array) => {
console.log('prev: ', prev)
console.log('cur: ', cur)
console.log('index: ', index)
console.log('array: ', array)
console.log('----------------')
return prev + cur
})
/*
数组中有三位元素,但函数只会执行两次,具体如下。
第一次执行输出:
prev: 2 // 由于未设置初始值,所以第一次执行prev为数组第一个元素2
cur: 4 //数组第二个元素为当前被处理的元素
index: 1 //当前被处理元素4对应的下标
array: [ 2, 4, 6 ] // 调用reduce的数组
----------------
第二次执行输出:
prev: 6 //上一次调用回调return的值,2 + 4 = 6,所以此处prev为6
cur: 6 //数组元素由左到右依次进行处理,此处处理数组的第三个元素6
index: 2 // 当前被处理元素6对应的下标
array: [ 2, 4, 6 ] // 调用reduce的数组
----------------
arr => [2, 4, 6]
sum => 12
*/
设置初始值情况
let arr = [2, 4, 6]
let sum = arr.reduce((prev, cur, index, array) => {
console.log('prev: ', prev)
console.log('cur: ', cur)
console.log('index: ', index)
console.log('array: ', array)
console.log('----------------')
return prev + cur
},10)
/*
设置初始值,函数执行3次,具体如下。
第一次执行输出:
prev: 10 // 此处设置了初始值10
cur: 2 //由左到右,数组第一个元素2
index: 0 //当前被处理元素2对应的下标
array: [ 2, 4, 6 ] // 调用reduce的数组
----------------
第二次执行输出:
prev: 12 //上一次调用回调return的值,10 + 2 = 12,所以此处prev为12
cur: 4 //由左到右依次进行处理,此处处理数组的第二个元素4
index: 1 // 当前被处理元素4对应的下标
array: [ 2, 4, 6 ] // 调用reduce的数组
----------------
第三次执行输出:
prev: 16 //上一次调用回调return的值,12 + 4 = 16,所以此处prev为16
cur: 6 //由左到右依次进行处理,此处处理数组的第三个元素6
index: 2 // 当前被处理元素6对应的下标
array: [ 2, 4, 6 ] // 调用reduce的数组
----------------
arr => [2, 4, 6]
sum => 22
*/
基本用法如上,自己动手实践一遍,就可以大致有些了解,以下会介绍一些实际应用。
实际应用
数组求和,求积
let arr = [1, 2, 3]
let sum = arr.reduce((prev, cur) => prev + cur)
let mul = arr.reduce((prev, cur) => prev * cur)
计算数组中每个元素出现的次数
// 不使用reduce方法
let arr = ['a', 'b', 'c', 'a', 'c']
let obj = {}
arr.forEach(item => {
if (item in obj) {
obj[item]++
} else {
obj[item] = 1
}
})
// obj => { a: 2, b: 1, c: 2 }
// 使用reduce
let res = arr.reduce((prev, cur) => {
if (cur in prev) {
prev[cur]++
} else {
prev[cur] = 1
}
return prev
}, {})
// res => { a: 2, b: 1, c: 2 }
数组去重
let arr = [5, 1, 1, 2, 3, 4, 3, 5]
// Set方法
let res = Array.from(new Set(arr)) // res => [ 5, 1, 2, 3, 4 ]
// forEach方法
let resArr = []
arr.forEach(item => {
if (!resArr.includes(item)) {
resArr.push(item)
}
}) // resArr => [ 5, 1, 2, 3, 4 ]
// reduce方法
let resArr = arr.reduce((prev, cur) => {
if (!prev.includes(cur)) {
prev.push(cur)
// prev.concat(cur)
}
return prev
}, []) // resArr => [ 5, 1, 2, 3, 4 ]
将多维数组转化为一维数组
let arr = [ [0, 1], [2, 3], [4, 5, [2, 3]] ]
// flat()
let res = arr.flat(Infinity) // res => [0, 1, 2, 3, 4, 5, 2, 3]
// reduce()
const flat = (item) => {
let res = item.reduce((prev, cur) => {
if (cur instanceof Array) {
// Array.isArray(cur) <=> cur instanceof Array
return prev.concat(flat(cur))
} else {
return prev.concat(cur)
}
}, [])
return res
}
// flat(arr) => [0, 1, 2, 3, 4, 5, 2, 3]
暂时总结这些实际应用用法,后面会持续更新。