reduce函数介绍(1)
相关知识点reduce函数:(reduce 是 JavaScript 数组方法中最强大、最灵活的一个——几乎所有数组操作都可以用 reduce 实现。它本质上是把一个数组"归纳"成一个值。)
1 array.reduce((accumulator, currentValue, index, array) => {
2 // 返回新的 accumulator
3 }, initialValue)
4
5 /*
6 accumulator(累加器) 上一次回调的返回值,或 initialValue
7 currentValue(当前值) 当前正在处理的元素
8 index(索引) 当前元素的索引(可选)
9 array(原数组) 调用 reduce 的数组(可选)
10 initialValue(初始值) 第一次调用回调时的 accumulator
11
12 */
13
14 [1, 2, 3, 4].reduce((acc, cur) => acc + cur, 0)
15
16 acc cur return
17 ─────────────────────
18 0 + 1 = 1 ← 第1次
19 1 + 2 = 3 ← 第2次
20 3 + 3 = 6 ← 第3次
21 6 + 4 = 10 ← 第4次
22
23 最终结果: 10
所有数组方法都可以用 reduce 模拟
const arr = [1, 2, 3, 4, 5]
// ─── map ───
arr.map(x => x * 2)
// 等价于
arr.reduce((acc, cur) => [...acc, cur * 2], [])
// [2, 4, 6, 8, 10]
// ─── filter ───
arr.filter(x => x > 2)
// 等价于
arr.reduce((acc, cur) => cur > 2 ? [...acc, cur] : acc, [])
// [3, 4, 5]
// ─── find ───
arr.find(x => x > 3)
// 等价于
arr.reduce((acc, cur) => (acc !== undefined ? acc : (cur > 3 ? cur : undefined)), undefined)
// 4
// ─── some ───
arr.some(x => x > 4)
// 等价于
arr.reduce((acc, cur) => acc || cur > 4, false)
// true
// ─── every ───
arr.every(x => x > 0)
// 等价于
arr.reduce((acc, cur) => acc && cur > 0, true)
// true
// ─── flat ───
[[1, 2], [3, 4], [5]].flat()
// 等价于
[[1, 2], [3, 4], [5]].reduce((acc, cur) => [...acc, ...cur], [])
// [1, 2, 3, 4, 5]
// ─── forEach ───
arr.forEach(x => console.log(x))
// 等价于
arr.reduce((_, cur) => { console.log(cur) }, null)
三、前端经典实战场景
场景 1:求和 / 求积 / 统计
1 // 求和
2 const numbers = [1, 2, 3, 4, 5]
3 const sum = numbers.reduce((acc, cur) => acc + cur, 0)
4 console.log(sum) // 15
5
6 // 求积
7 const product = numbers.reduce((acc, cur) => acc * cur, 1)
8 console.log(product) // 120
9
10 // 统计出现次数
11 const fruits = ['苹果', '香蕉', '苹果', '橘子', '香蕉', '苹果']
12 const count = fruits.reduce((acc, cur) => {
13 acc[cur] = (acc[cur] || 0) + 1
14 return acc
15 }, {})
16 console.log(count) // { 苹果: 3, 香蕉: 2, 橘子: 1 }
场景 2:数组去重
1 const arr = [1, 2, 2, 3, 4, 4, 5, 1, 3]
2
3 // 方法1:基本去重
4 const unique = arr.reduce((acc, cur) => {
5 if (!acc.includes(cur)) {
6 acc.push(cur)
7 }
8 return acc
9 }, [])
10 console.log(unique) // [1, 2, 3, 4, 5]
11
12 // 方法2:Set 去重(性能更好,但 reduce 可以加更多逻辑)
13 const unique2 = arr.reduce((acc, cur) => {
14 return acc.add(cur)
15 }, new Set())
16 console.log([...unique2]) // [1, 2, 3, 4, 5]
17
18 // 方法3:对象去重(保留最后一次出现的重复项)
19 const items = [
20 { id: 1, name: 'A' },
21 { id: 2, name: 'B' },
22 { id: 1, name: 'C' }, // 重复 id
23 { id: 3, name: 'D' }
24 ]
25 const uniqueById = items.reduce((acc, cur) => {
26 acc[cur.id] = cur // 后出现的覆盖先出现的
27 return acc
28 }, {})
29 console.log(Object.values(uniqueById))
30 // [{ id: 1, name: 'C' }, { id: 2, name: 'B' }, { id: 3, name: 'D' }]
场景 3:数组转对象(分组)
1 // 按属性分组
2 const users = [
3 { name: '张三', role: 'admin' },
4 { name: '李四', role: 'user' },
5 { name: '王五', role: 'admin' },
6 { name: '赵六', role: 'user' },
7 { name: '钱七', role: 'guest' }
8 ]
9
10 const groupByRole = users.reduce((acc, user) => {
11 (acc[user.role] = acc[user.role] || []).push(user)
12 return acc
13 }, {})
14
15 console.log(groupByRole)
16 // {
17 // admin: [{ name: '张三', role: 'admin' }, { name: '王五', role: 'admin' }],
18 // user: [{ name: '李四', role: 'user' }, { name: '赵六', role: 'user' }],
19 // guest: [{ name: '钱七', role: 'guest' }]
20 // }
21
22 // 通用分组函数
23 function groupBy(arr, keyFn) {
24 return arr.reduce((acc, item) => {
25 const key = typeof keyFn === 'function' ? keyFn(item) : item[keyFn]
26 (acc[key] = acc[key] || []).push(item)
27 return acc
28 }, {})
29 }
30
31 // 使用
32 console.log(groupBy(users, 'role'))
33 console.log(groupBy(users, (u) => u.name.length > 1 ? '长名' : '短名'))
场景 4:扁平化嵌套数组
1 // 扁平化一层
2 const nested = [[1, 2], [3, 4], [5, 6]]
3 const flat = nested.reduce((acc, cur) => [...acc, ...cur], [])
4 // [1, 2, 3, 4, 5, 6]
5
6 // 递归扁平化任意深度
7 function flattenDeep(arr) {
8 return arr.reduce((acc, cur) => {
9 return Array.isArray(cur)
10 ? [...acc, ...flattenDeep(cur)]
11 : [...acc, cur]
12 }, [])
13 }
14
15 console.log(flattenDeep([1, [2, [3, [4, 5]]]]))
16 // [1, 2, 3, 4, 5]
17
18 // 扁平化 + 去重 + 排序
19 const messy = [[3, 1], [2, 3], [1, [4, 2]]]
20 const result = messy
21 .reduce((acc, cur) => [...acc, ...(Array.isArray(cur) ? flattenDeep(cur) : [cur])], [])
22 .reduce((acc, cur) => acc.includes(cur) ? acc : [...acc, cur], [])
23 .sort((a, b) => a - b)
24 console.log(result) // [1, 2, 3, 4]

浙公网安备 33010602011771号