前言
在JavaScript
编程中,对数组进行分组是一项常见的任务。无论是根据特定属性将对象分组,还是按照某些规则重新组织数组元素,分组操作在日常开发中都是常见的。过去,为了实现这一目标,通常需要编写自定义的分组函数或者使用第三方库,比如lodash
的groupBy
函数。然而,好消息是,JavaScript
正逐渐引入原生的分组方法,使我们的开发工作更加便捷。在本文中,我们将探讨JavaScript
的新特性,即Object.groupBy
和Map.groupBy
,这两个新特性将使数组分组操作更加容易。
分组操作的背景
假设现在有一个包含人员信息的数组,每个人都有姓名和年龄属性,需求想要按照他们的年龄将他们分组。在以前的JavaScript
中,可能需要编写自定义的分组函数,或者使用forEach
或reduce
等方法,来实现分组操作。如下:
ini
const people = [
{ name: "Alice", age: 28 },
{ name: "Bob", age: 30 },
{ name: "Eve", age: 28 },
];
// 使用forEach进行分组
const peopleByAge = {};
people.forEach((person) => {
const age = person.age;
if (!peopleByAge[age]) {
peopleByAge[age] = [];
}
peopleByAge[age].push(person);
});
// 使用reduce进行分组
const peopleByAge = people.reduce((acc, person) => {
const age = person.age;
if (!acc[age]) {
acc[age] = [];
}
acc[age].push(person);
return acc;
}, {});
运行结果:
无论是使用forEach
还是reduce
,这些传统方法都需要手动检查分组键是否存在,如果不存在则创建一个空数组,然后将对象推入该数组中。上面的示例代码相对繁琐,可能需要不少工作量,尤其是在复杂的应用程序中。
下面就来Javascript
即将支持的两种新特性是如何实现上述需求的→
Object.groupBy:原生分组方法
JavaScript
新引入的Object.groupBy
方法,使数据分组将变得更加简单和高效。使用Object.groupBy
,可以按照指定的属性或规则将数组中的对象分组,而不需要手动管理分组过程。如下:
ini
const people = [
{ name: "Alice", age: 28 },
{ name: "Bob", age: 30 },
{ name: "Eve", age: 28 },
];
const peopleByAge = Object.groupBy(people, (person) => person.age);
在控制台运行代码可以看到:
如上图所示,使用Object.groupBy
,只需提供一个回调函数,该回调函数将确定如何进行分组。在这种情况下,就可以按照人的年龄属性进行分组,这是不是比传统的手动分组方法要简单得多。
然而,需要注意的是,Object.groupBy
返回一个无原型的对象,这意味着它不会继承Object.prototype
上的任何属性或方法。因此,不能像通常那样使用hasOwnProperty
等方法。此外,回调函数应返回一个字符串或符号,否则它将被强制转换为字符串。
arduino
console.log(peopleByAge.hasOwnProperty("28"));
Map.groupBy:返回Map对象的分组方法
除了Object.groupBy
,JavaScript
还引入了Map.groupBy
方法,该方法在执行分组操作时返回一个Map
对象。与Object.groupBy
相比,Map.groupBy
提供了更多的灵活性,因为它允许返回任何类型的值,并且可以使用Map
的各种方法来操作结果。如下:
ini
const ceo = { name: "Jamie", age: 40, reportsTo: null };
const manager = { name: "Alice", age: 28, reportsTo: ceo };
const people = [
ceo,
manager,
{ name: "Bob", age: 30, reportsTo: manager },
{ name: "Eve", age: 28, reportsTo: ceo },
];
const peopleByManager = Map.groupBy(people, (person) => person.reportsTo);
运行结果:
在这个示例中,我们根据人员的上级进行分组。一个重要的注意点是,要从Map
中检索对象,必须使用相同的对象引用。如果传递的对象虽然内容相同但不是同一个对象,将无法从Map
中检索到结果。
php
peopleByManager.get(ceo); // 返回与ceo对象相关的人员
peopleByManager.get({ name: "Jamie", age: 40, reportsTo: null }); // 返回undefined,因为这不是同一个对象
Map.groupBy
的优势在于,它返回一个Map
对象,可以使用Map
的方法来处理分组后的结果,这在某些场景下非常有用。
分组方法的兼容性
目前Object.groupBy
和Map.groupBy
是TC39 提案的一部分,目前处于第3 阶段。这表明它们有望成为JavaScript
标准的一部分。在实际应用中,Chrome 117
已经支持这两个方法,而Firefox Nightly
则在实验标志下实现了它们。Safari
也已经实现了类似的方法,可以期待它们会在不久的将来更新以提供更好的支持。
上面示例代码运行的浏览器版本是118.0.5993.89
,故可以正确的打印出结果。
疑问
你可能会疑惑为什么这些分组方法被实现为Object.groupBy
和Map.groupBy
,而不是Array.prototype.groupBy
。这是因为在过去,有一些库曾经在Array.prototype
上添加了不兼容的groupBy
方法,这导致了一些兼容性问题,所以就没有在在Array.prototype
上实现。
总结
本文介绍了JavaScript
中即将引入的Object.groupBy
和Map.groupBy
两种原生分组方法的使用。这些两种原生分组方法将填补JavaScript
开发中的空白,使前端开发人员能够更轻松地进行分组操作,提高了编程效率和代码质量。希望本文能对你以后的工作有所帮助。
后语
小伙伴们,如果觉得本文对你有些许帮助,点个👍或者➕个关注再走吧^_^ 。另外如果本文章有问题或有不理解的部分,欢迎大家在评论区评论指出,我们一起讨论共勉。