在处理复杂的数据结构时,我们经常会遇到需要将扁平化的对象数组按照某个特定属性进行归类的情况。例如,从后端接口获取到一个包含多个用户信息的数组,每个用户对象中都有一个所属部门的属性,前端展示时需要按部门将这些用户分组显示。这种将线性数据转换为树状或按维度归类的过程,就是典型的数组分组操作。掌握高效的分组方法,能够让数据处理逻辑更加清晰,显著提升前端渲染性能。

使用原生JavaScript的reduce方法实现分组
在没有外部库支持的环境下,Array.prototype.reduce是实现数组分组最核心且最灵活的原生方法。reduce方法接收一个回调函数和一个初始值,通过遍历数组将每个元素累积到一个最终的结果中。在分组场景下,我们将初始值设为一个空对象,然后在每次遍历时判断当前元素的分组属性值是否已经存在于对象中,如果不存在则初始化一个空数组,并将当前元素推入对应的数组中。
下面是一个具体的代码示例,展示如何将一个包含用户信息的对象数组按照部门属性进行分组。在这个示例中,我们定义了一个groupBy函数,它接受一个数组和一个迭代函数作为参数,返回一个按键值分组的新对象。这种实现方式不仅适用于简单的属性提取,还可以处理复杂的分组条件。
const users = [
{ name: '张三', department: '研发部' },
{ name: '李四', department: '市场部' },
{ name: '王五', department: '研发部' },
{ name: '赵六', department: '市场部' }
];
// 自定义groupBy函数
function groupBy(array, iteratee) {
return array.reduce((result, currentItem) => {
// 获取分组键名
const key = typeof iteratee === 'function' ? iteratee(currentItem) : currentItem[iteratee];
// 如果结果对象中不存在该键,则初始化为空数组
if (!result[key]) {
result[key] = [];
}
// 将当前元素推入对应的分组数组中
result[key].push(currentItem);
return result;
}, {}); // 初始值为空对象
}
// 按部门分组
const groupedUsers = groupBy(users, 'department');
console.log(groupedUsers);
使用reduce方法的优势在于其极高的灵活性,你可以完全控制分组逻辑,甚至可以在遍历时对数据进行额外的转换或过滤。然而,这种方式的缺点也比较明显,每次都需要手动编写一段相对冗长的逻辑代码,如果项目中有大量分组需求,代码复用率较低,且容易出现拼写错误或逻辑漏洞。
借助Lodash工具库快速实现groupBy
对于大多数现代前端项目而言,Lodash已经成为了标配的工具库。Lodash提供了大量经过性能优化的工具函数,其中就包含了_.groupBy方法。使用Lodash的好处在于无需自己维护底层逻辑,只需简单调用即可完成复杂的分组操作,代码更加简洁直观,极大地提升了开发效率。
_.groupBy方法接收两个参数:第一个是需要遍历的集合,第二个是迭代函数或者属性键名。它会遍历集合中的每个元素,将迭代函数的返回值作为键名,将对应的元素组成数组作为键值,最终返回一个分组后的对象。下面是使用Lodash实现上述同样分组逻辑的代码示例。
// 引入lodash库
const _ = require('lodash');
const users = [
{ name: '张三', department: '研发部' },
{ name: '李四', department: '市场部' },
{ name: '王五', department: '研发部' },
{ name: '赵六', department: '市场部' }
];
// 直接使用属性名进行分组
const groupedUsers = _.groupBy(users, 'department');
console.log(groupedUsers);
// 也可以使用函数进行更复杂的分组逻辑
const groupedByLength = _.groupBy(users, function(user) {
return user.name.length;
});
console.log(groupedByLength);
Lodash的_.groupBy方法不仅支持直接传入属性名,还支持传入自定义函数,甚至支持路径字符串。它的内部实现也考虑了各种边界情况,比如处理null或undefined等。不过,引入Lodash虽然方便,但也意味着增加了项目的打包体积。如果项目对体积要求极其苛刻,或者只有少数几处需要分组,单独引入Lodash可能显得有些过重。
拥抱新标准:Object.groupBy的实战应用
随着ECMAScript标准的不断演进,JavaScript原生终于迎来了内置的分组方法。在最新的ES2024规范中,Object.groupBy和Map.groupBy被正式引入。这意味着开发者不再需要依赖reduce手写逻辑,也不必引入Lodash,直接使用原生方法即可完成分组操作,这是JavaScript语言层面的一大进步。
Object.groupBy方法接收一个可迭代对象和一个回调函数,回调函数返回的值将作为分组键。需要注意的是,Object.groupBy返回的对象是一个null原型对象,这意味着它没有Object.prototype上的方法,如hasOwnProperty等,这在一定程度上避免了原型链污染的风险。下面是使用新标准进行分组的代码示例。
const users = [
{ name: '张三', department: '研发部' },
{ name: '李四', department: '市场部' },
{ name: '王五', department: '研发部' },
{ name: '赵六', department: '市场部' }
];
// 使用Object.groupBy进行分组
const groupedUsers = Object.groupBy(users, (user) => user.department);
console.log(groupedUsers);
// 如果需要根据某个条件进行分组,比如名字长度是否大于2
const groupedByLength = Object.groupBy(users, (user) => {
return user.name.length > 2 ? '长名字' : '短名字';
});
console.log(groupedByLength);
Object.groupBy的语法非常简洁,且作为原生方法,其执行效率在未来的引擎优化中会越来越好。然而,由于这是一个非常新的特性,目前在一些老旧浏览器或较低版本的Node.js环境中可能还不支持。因此,在使用Object.groupBy时,需要确认目标运行环境的兼容性,或者配合Babel等编译工具进行降级处理。如果需要返回Map结构,还可以使用Map.groupBy方法,进一步丰富了数据结构的表达形式。
JavaScriptgroupBy对象数组分组修改时间:2026-08-27 14:54:56