先从一段接口数据说起
后端返回一个订单数组,每条带 status 字段,页面要按状态分成待付款、已发货、已完成三块。最直接的写法是 reduce,累积一个对象,键当分组名。
const g = list.reduce((m, it) => { (m[it.status] = m[it.status] || []).push(it); return m; }, {});这段代码兼容性最好,任何还活着的浏览器都能跑。缺点是每次都要判空,写多了显得啰嗦。
新项目可以直接用 Object.groupBy
ES2024 加进来的静态方法,Node 21 以上、Chrome 117 以上支持。写法变成 Object.groupBy(list, it => it.status),返回的对象键就是分组值。要注意它返回的是无原型对象,直接丢给 JSON.stringify 没问题,但调 hasOwnProperty 会报错,得用 Object.hasOwn。
键是对象或者需要 Map 语义时,用 Map.groupBy,取的时候用 get 而不是方括号。分组键为 undefined 或者 null 时,结果里会出现一个 undefined 键,遍历时容易漏掉,先过滤一遍更稳。
几个实际会踩的点
- 数字键在普通对象里会被排序,顺序和原数组不一致,在意顺序就用 Map
- 分组后每组还是原对象引用,改一个字段两边都变
- 数组很大时 reduce 每轮都建数组,内存涨得快,可以改成先排序再切片
线上项目求稳就 reduce,新项目、构建工具链跟得上就用 groupBy,代码短一半,可读性也好。两者性能差距在同量级,别为这个纠结。