reduce适合数据聚合如分组统计,以对象或Map为初始值,按字段归类并计数、收集或求和;支持多字段嵌套分组;Map更安全,可避免键类型问题。

reduce 是 JS 数组中非常强大的方法,适合做数据聚合类操作,比如分组统计。它通过一个累加器(accumulator)逐步处理每个元素,最终返回单个值——这个“单个值”完全可以是一个按条件分好组的对象或 Map。
核心思路:用对象或 Map 作为初始值
分组统计的本质是把数组元素按某个字段(如 category、status、type)归类,并对每组做计数、求和、收集等操作。reduce 的初始值设为一个空对象 {} 或 new Map(),然后在回调中根据当前项的分组依据更新对应组的数据。
- 若统计每组数量,就给对应 key 的值 +1
- 若收集每组所有项,就用数组 push 当前项
- 若计算每组总和,就累加某个数值字段
示例:按类型分组并统计数量
假设有商品列表:
const products = [{ name: '苹果', type: '水果' },
{ name: '香蕉', type: '水果' },
{ name: '牛奶', type: '乳品' },
{ name: '面包', type: '烘焙' }
];
用 reduce 实现分组计数:
const grouped = products.reduce((acc, item) => {const key = item.type;
acc[key] = (acc[key] || 0) + 1;
return acc;
}, {});
结果:{ 水果: 2, 乳品: 1, 烘焙: 1 }
进阶:按多字段分组 + 复杂统计
比如统计「每个分类下不同状态的商品数量」:
{ cat: 'A', status: 'active' },
{ cat: 'A', status: 'inactive' },
{ cat: 'B', status: 'active' }
];
构建嵌套结构:
const result = data.reduce((acc, item) => {const { cat, status } = item;
if (!acc[cat]) acc[cat] = {};
acc[cat][status] = (acc[cat][status] || 0) + 1;
return acc;
}, {});
结果:{ A: { active: 1, inactive: 1 }, B: { active: 1 } }
小技巧:用 Map 替代普通对象更安全
当分组键可能是任意字符串(含特殊字符)、数字或对象时,普通对象可能出问题(如 key 被转成字符串、原型污染风险)。推荐用 Map:
const map = data.reduce((acc, item) => {const key = item.type;
acc.set(key, (acc.get(key) || 0) + 1);
return acc;
}, new Map());
后续可用 Object.fromEntries(map) 转成普通对象,或直接用 map.forEach 遍历。











