在JAVAScript编程中,对数组进行分组是一项常见的任务。无论是根据特定属性将对象分组,还是按照某些规则重新组织数组元素,分组操作在日常开发中都是常见的。过去,为了实现这一目标,通常需要编写自定义的分组函数或者使用第三方库,比如lodash的groupBy函数。然而,好消息是,JavaScript正逐渐引入原生的分组方法,使我们的开发工作更加便捷。在本文中,我们将探讨JavaScript的新特性,即Object.groupBy和Map.groupBy,这两个新特性将使数组分组操作更加容易。
假设现在有一个包含人员信息的数组,每个人都有姓名和年龄属性,需求想要按照他们的年龄将他们分组。在以前的JavaScript中,可能需要编写自定义的分组函数,或者使用forEach或reduce等方法,来实现分组操作。如下:
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即将支持的两种新特性是如何实现上述需求的→
JavaScript新引入的Object.groupBy方法,使数据分组将变得更加简单和高效。使用Object.groupBy,可以按照指定的属性或规则将数组中的对象分组,而不需要手动管理分组过程。如下:
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等方法。此外,回调函数应返回一个字符串或符号,否则它将被强制转换为字符串。
console.log(peopleByAge.hasOwnProperty("28"));
图片
除了Object.groupBy,JavaScript还引入了Map.groupBy方法,该方法在执行分组操作时返回一个Map对象。与Object.groupBy相比,Map.groupBy提供了更多的灵活性,因为它允许返回任何类型的值,并且可以使用Map的各种方法来操作结果。如下:
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中检索到结果。
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开发中的空白,使前端开发人员能够更轻松地进行分组操作,提高了编程效率和代码质量。希望本文能对你以后的工作有所帮助。