数组聚合应首选 reduce 一次遍历完成多维归并,通过初始化对象 accumulator 实现按字段分组累加,再用 Object.values() 提取结果;支持条件筛选、多字段分组及嵌套结构,语义清晰且性能更优。
用数组方法做数据聚合,核心在于一次遍历、多维归并,而不是反复 filter + reduce。关键不是堆砌方法,而是选对主干——reduce 是最适配聚合逻辑的原生方法,它天然支持状态累积、结构重组和条件分流。
按字段分组并累加数值
这是最常见的聚合需求,比如按用户 ID 统计总消费、按项目类型汇总工时和金额。关键是把分组键作为对象属性,用 reduce 构建映射表:
- 初始化 accumulator 为一个空对象(
{}),每个键对应一个分组 - 每次迭代中,根据当前项的分组字段(如
item.ProjectType)获取或创建该组对象 - 对目标数值字段(如
Amount、Hours)做累加,不存在则设初值 0 - 最后用
Object.values()提取结果数组,保持扁平结构
示例:对 frames 按 ProjectType 聚合 Amount 和 Hours
const result = frames.reduce((groups, item) => {
const key = item.ProjectType;
if (!groups[key]) {
groups[key] = { ProjectType: key, TotalAmount: 0, TotalHours: 0 };
}
groups[key].TotalAmount += item.Amount || 0;
groups[key].TotalHours += item.Hours || 0;
return groups;
}, {});
const groupedArray = Object.values(result); // [{ ProjectType:"Lima", TotalAmount:60, TotalHours:15 }, ...]
条件筛选+聚合一步到位
不需要先 filter 再 reduce,直接在回调里加判断。既减少遍历次数,又避免中间数组开销:
- 累加器初始值按需设定(如数字用
0,对象用{},数组用[]) - 在回调内部用
if或三元判断决定是否参与聚合 - 例如只统计已支付订单总额:
order.status === 'paid' ? sum + order.amount : sum
多字段分组与嵌套结构生成
当分组依据不止一个字段(如 type 和 status),可拼接键名或用 JSON.stringify 包裹数组:
- 简单拼接:
const key = `${item.type}-${item.status}` - 安全方式(防特殊字符):
const key = JSON.stringify([item.type, item.status]) - 若需保留原始结构层级,可在 accumulator 中嵌套对象,逐层构建
替代 for 循环,但不替代逻辑设计
reduce 不是“高级写法秀”,它的优势在于显式表达聚合意图。相比手写 for 循环:
- 避免手动维护索引、临时变量和边界判断
- accumulator 始终代表“到目前为止的聚合结果”,语义清晰
- 配合解构、可选链(
?.)和空值合并(??),能优雅处理缺失字段
真正灵活的聚合,不靠方法数量堆砌,而靠 reduce 的 accumulator 设计——它可以是数字、对象、数组,甚至函数或 Map 实例,取决于你要输出什么结构。

















