Что такое Array.prototype.group и Object.groupBy в JavaScript?
Что это такое
Одно время в TC39 обсуждалось предложение добавить метод Array.prototype.group(), который бы группировал элементы массива по ключу, возвращаемому функцией-колбэком, прямо на прототипе массива — по аналогии с map, filter, reduce.
Однако выяснилось, что имя group конфликтует с уже существующим нестандартным свойством Array.prototype.group, добавленным движком MooTools и всё ещё встречающимся на старых сайтах. Из-за риска сломать существующие страницы TC39 отказался от расширения прототипа массива и переработал предложение в два статических метода: Object.groupBy() и Map.groupBy().
Object.groupBy()
Object.groupBy(items, callback) принимает итерируемый объект (массив, Set, генератор и т.д.) и функцию, вызываемую для каждого элемента. Функция возвращает строку или символ — ключ группы. Результат — обычный объект без прототипа (Object.create(null)), где ключи — это группы, а значения — массивы элементов, попавших в эту группу.
const products = [
{ name: 'Яблоко', type: 'fruit' },
{ name: 'Морковь', type: 'vegetable' },
{ name: 'Банан', type: 'fruit' },
];
const grouped = Object.groupBy(products, (item) => item.type);
// {
// fruit: [{ name: 'Яблоко', ... }, { name: 'Банан', ... }],
// vegetable: [{ name: 'Морковь', ... }]
// }
Объект создаётся без прототипа специально, чтобы ключи вроде constructor или toString не конфликтовали со встроенными свойствами объекта.
Map.groupBy()
Map.groupBy(items, callback) работает так же, но возвращает Map вместо обычного объекта. Это полезно, когда ключом группы должно быть не только строка/символ, а произвольное значение — число, объект, NaN и т.д., потому что ключи Map не приводятся к строке.
const inventory = [
{ name: 'asparagus', quantity: 5 },
{ name: 'bananas', quantity: 0 },
{ name: 'goat', quantity: 23 },
];
const result = Map.groupBy(inventory, ({ quantity }) => quantity > 0);
// Map(2) { true => [ {asparagus...}, {goat...} ], false => [ {bananas...} ] }
Чем отличаются от reduce-группировки
До появления этих методов группировку писали через reduce:
const grouped = products.reduce((acc, item) => {
(acc[item.type] ??= []).push(item);
return acc;
}, {});
Object.groupBy/Map.groupBy — это тот же паттерн, но встроенный в язык: короче, декларативнее и без риска случайно перезаписать прототипные свойства.
Поддержка
Оба метода — часть стандарта ECMAScript 2024 (ES2024) и поддерживаются в актуальных версиях Chrome, Firefox, Safari и Node.js (начиная с 21 версии). Для старых окружений нужен полифилл или fallback на reduce.
Итог
Array.prototype.group — это историческое название несостоявшегося метода, который в итоге стал парой статических методов Object.groupBy и Map.groupBy, добавленных в ES2024 для декларативной группировки элементов коллекции по ключу.
Что хочет услышать интервьюер
Кандидат знает, что финальное имя метода — не Array.prototype.group, а Object.groupBy/Map.groupBy
Объясняет, почему предложение изменили (конфликт с legacy-свойством MooTools на Array.prototype)
Понимает сигнатуру: коллбэк возвращает ключ группы для каждого элемента
Знает разницу между Object.groupBy (обычный объект без прототипа) и Map.groupBy (Map с произвольными ключами)
Может сравнить с классическим способом группировки через reduce
Пример: Object.groupBy — группировка по типу
const products = [
{ name: 'Яблоко', type: 'fruit' },
{ name: 'Морковь', type: 'vegetable' },
{ name: 'Банан', type: 'fruit' },
];
const grouped = Object.groupBy(products, (item) => item.type);
console.log(grouped.fruit);
// [{ name: 'Яблоко', type: 'fruit' }, { name: 'Банан', type: 'fruit' }]
Пример: Map.groupBy — группировка по булеву значению
const inventory = [
{ name: 'asparagus', quantity: 5 },
{ name: 'bananas', quantity: 0 },
{ name: 'goat', quantity: 23 },
];
const restock = Map.groupBy(inventory, ({ quantity }) => quantity === 0);
console.log(restock.get(true));
// [{ name: 'bananas', quantity: 0 }]
Пример: Аналог через reduce (до ES2024)
function groupBy(array, keyFn) {
return array.reduce((acc, item) => {
const key = keyFn(item);
// создаём массив для новой группы, если её ещё нет
(acc[key] ??= []).push(item);
return acc;
}, {});
}
Типичные ошибки
Утверждают, что метод называется Array.prototype.group и вызывается на массиве как array.group(...)
Не знают о конфликте имён, из-за которого метод не попал в Array.prototype
Путают порядок аргументов callback или забывают, что он возвращает именно ключ группы, а не сам элемент
Не упоминают, что Object.groupBy возвращает объект без прототипа (Object.create(null))
Не могут объяснить, зачем нужен отдельный Map.groupBy, если уже есть Object.groupBy


