Array.prototype.group()

实验性: 这是一项实验性技术
在将其用于生产之前,请仔细检查浏览器兼容性表格

group() 方法根据提供的测试函数返回的字符串值,将调用数组的元素分组。返回的对象具有每个组的单独属性,其中包含组中的元素数组。

当分组名称可以用字符串表示时,应使用此方法。如果你需要使用某个任意值作为键来分组元素,请改用 Array.prototype.groupToMap() 方法。

语法

group(callbackFn)
group(callbackFn, thisArg)

参数

callbackFn

为数组中的每个元素执行的函数。它应该返回一个值,可以被强制转换成属性键(字符串或 symbol),用于指示当前元素所属的分组。该函数被调用时将传入以下参数:

element

数组中当前正在处理的元素。

index

正在处理的元素在数组中的索引。

array

调用了 group() 的数组本身。

thisArg 可选

执行 callbackFn 时用作 this 的值。参见迭代方法

返回值

一个带有所有分组属性的 null 原型对象,每个属性都分配了一个包含相关组元素的数组。

描述

group() 方法是一个迭代方法。它为数组中的每个元素调用一次提供的 callbackFn 函数,并返回一个字符串或 symbol(不属于这两种类型的值将被强制转换为字符串),用于指示元素所属的分组。对于每个由回调函数返回的唯一分组名称,在结果对象中创建一对新属性和数组。每个元素将被添加到其对应分组属性的数组中。

callbackFn 作用于数组中的每个索引,而不仅仅是已赋值的索引。在稀疏数组中,空槽的行为表现与 undefined 相同。

group() 方法是一个复制方法。它不会改变 this,而是返回一个包含与原始数组相同元素的数组对象。但是,作为 callbackFn 的函数可以更改数组。请注意,在第一次调用 callbackFn 之前,数组的长度已经被保存。因此:

  • 当开始调用 group() 时,callbackFn 将不会访问超出数组初始长度的任何元素。
  • 对已访问索引的更改不会导致再次在这些元素上调用 callbackFn
  • 如果数组中一个现有的、尚未访问的元素被 callbackFn 更改,则它传递给 callbackFn 的值将是该元素被修改后的值。被删除的元素将被当作 undefined 而被访问。

警告: 上述类型的并发修改经常导致难以理解的代码,通常应避免(特殊情况除外)。

返回的对象引用与原始数组相同的元素(不是深拷贝)。更改这些元素的内部结构将反映在原始数组和返回的对象中。

group() 方法是通用的。它只期望 this 值具有 length 属性和整数键的属性。

示例

使用 group()

首先,我们定义一个包含代表各种食品库存的对象的数组。每种食品都有一个 type 和一个 quantity 属性。

const inventory = [
  { name: "asparagus", type: "vegetables", quantity: 5 },
  { name: "bananas", type: "fruit", quantity: 0 },
  { name: "goat", type: "meat", quantity: 23 },
  { name: "cherries", type: "fruit", quantity: 5 },
  { name: "fish", type: "meat", quantity: 22 },
];

下面的代码根据元素的 type 属性的值对元素进行分组。

const result = inventory.group(({ type }) => type);

/* 结果是:
{
  vegetables: [
    { name: 'asparagus', type: 'vegetables', quantity: 5 },
  ],
  fruit: [
    { name: "bananas", type: "fruit", quantity: 0 },
    { name: "cherries", type: "fruit", quantity: 5 }
  ],
  meat: [
    { name: "goat", type: "meat", quantity: 23 },
    { name: "fish", type: "meat", quantity: 22 }
  ]
}
*/

箭头函数每次被调用时都只返回每个数组元素的 type 属性。请注意,函数参数 { type } 是一个函数参数的对象解构语法的基本示例。这会解构传递为参数的对象的 type 属性,并将其赋值给函数体中名为 type 的变量。这是一种非常简洁的访问函数中相关元素的值的方式。

我们还可以创建根据元素的一个或多个属性中的值推断的分组。下面是一个非常类似的示例,根据 quantity 字段的值将项目分为 okrestock 组。

function myCallback({ quantity }) {
  return quantity > 5 ? "ok" : "restock";
}

const result2 = inventory.group(myCallback);

/* 结果是:
{
  restock: [
    { name: "asparagus", type: "vegetables", quantity: 5 },
    { name: "bananas", type: "fruit", quantity: 0 },
    { name: "cherries", type: "fruit", quantity: 5 }
  ],
  ok: [
    { name: "goat", type: "meat", quantity: 23 },
    { name: "fish", type: "meat", quantity: 22 }
  ]
}
*/

在稀疏数组上使用 group()

当在稀疏数组上使用 group() 方法时,它会对空槽调用,并将其作为 undefined 值进行处理。

console.log([1, , 3].group((x) => x)); // { 1: [1], undefined: [undefined], 3: [3] }

在非数组对象上调用 group()

group() 方法读取 thislength 属性,然后访问每个整数索引。

const arrayLike = {
  length: 3,
  0: 2,
  1: 3,
  2: 4,
};
console.log(Array.prototype.group.call(arrayLike, (x) => x % 2));
// { 0: [2, 4], 1: [3] }

规范

Specification
Array Grouping
# sec-array.prototype.group

浏览器兼容性

BCD tables only load in the browser

参见