> Как работает функция groupBy в JavaScript (JavaScript)

Уровень: senior · Роль: frontend · Категория: Технические вопросы

Компании: Яндекс

Стек: JavaScript

> Пример ответа

Короткий ответ

groupBy - это статический метод Object.groupBy, появившийся в ES2024. Он группирует элементы итерируемого объекта по ключу, который возвращает callback-функция. Результат - обычный объект, где ключи - это значения, возвращённые колбэком, а значения - массивы исходных элементов. Метод не мутирует исходный массив и возвращает новый объект. Для Map существует аналогичный Map.groupBy.

Подробное объяснение

Object.groupBy(items, callbackFn) принимает два аргумента:

  • items - итерируемый объект (массив, Set, строка и т.д.)
  • callbackFn - функция, которая вызывается для каждого элемента и возвращает ключ группы (строку или Symbol)

Колбэк получает три аргумента: текущий элемент, индекс (или ключ для не-массивов) и сам итерируемый объект.

Ключевые особенности:

  • Возвращает объект с null-прототипом (без Object.prototype), что защищает от коллизий с унаследованными свойствами
  • Порядок ключей в объекте соответствует порядку первого появления группы
  • Элементы внутри каждой группы сохраняют исходный порядок
  • Не поддерживает thisArg - в отличие от Array.prototype.map или forEach
  • Если колбэк возвращает Symbol, он будет использован как ключ, но при обращении через точку это не сработает - только через скобочную нотацию

Map.groupBy работает аналогично, но возвращает Map, что удобно, когда ключи - не строки или нужен гарантированный порядок вставки.

На практике

Типичные сценарии использования:

  • Группировка пользователей по ролям или статусу
  • Агрегация транзакций по датам или категориям
  • Разделение данных на валидные/невалидные
  • Кластеризация элементов по вычисляемому признаку

До появления groupBy разработчики использовали reduce с ручной проверкой наличия ключа, что было более многословно и подвержено ошибкам. Метод значительно упрощает код и делает его более декларативным.

Важно помнить: метод доступен в Node.js 21+ и современных браузерах (Chrome 117+, Firefox 119+, Safari 17.4+). Для старых окружений нужен полифилл.

Пример кода

JAVASCRIPT
const users = [
{ name: 'Анна', role: 'admin', age: 30 },
{ name: 'Борис', role: 'user', age: 25 },
{ name: 'Виктор', role: 'admin', age: 35 },
{ name: 'Галина', role: 'user', age: 28 },
];
// Группировка по роли
const byRole = Object.groupBy(users, user => user.role);
// {
// admin: [{ name: 'Анна', ... }, { name: 'Виктор', ... }],
// user: [{ name: 'Борис', ... }, { name: 'Галина', ... }]
// }
// Группировка по возрастной категории
const byAgeGroup = Object.groupBy(users, user => {
if (user.age < 30) return 'young';
if (user.age < 35) return 'middle';
return 'senior';
});
// С Symbol в качестве ключа
const GROUP = Symbol('group');
const grouped = Object.groupBy([1, 2, 3], num => num > 1 ? GROUP : 'small');
// { small: [1], [Symbol(group)]: [2, 3] }
// Map.groupBy для нестроковых ключей
const byAge = Map.groupBy(users, user => user.age);
// Map(3) { 30 => [{...}], 25 => [{...}], 35 => [{...}] }

Как отвечать на собеседовании

Начните с краткого определения и синтаксиса. Затем покажите пример с реальными данными. Упомяните разницу между Object.groupBy и Map.groupBy. Обязательно скажите про null-прототип результата и отсутствие thisArg. Если спросят про альтернативы - покажите реализацию через reduce. Завершите упоминанием поддержки и полифиллов.

Хорошая структура ответа:

  1. Определение и сигнатура
  2. Пример использования
  3. Особенности реализации
  4. Сравнение с альтернативами
  5. Ограничения и поддержка

Что проверяет интервьюер

  • Понимание современных возможностей языка и их назначения
  • Умение объяснить разницу между похожими методами (Object.groupBy vs Map.groupBy)
  • Знание edge cases: Symbol-ключи, null-прототип, отсутствие thisArg
  • Способность предложить альтернативную реализацию через reduce
  • Осведомлённость о поддержке в различных окружениях
  • Понимание, когда метод уместен, а когда лучше использовать другие структуры данных

Типичные ошибки

  • Утверждение, что groupBy мутирует исходный массив - это не так
  • Забывают, что результат имеет null-прототип, и пытаются вызвать hasOwnProperty напрямую
  • Путают Object.groupBy с Array.prototype.groupBy (такого метода не существует)
  • Не упоминают, что колбэк не получает thisArg
  • Используют groupBy для группировки по числовым ключам, не учитывая, что они станут строками в объекте
  • Предлагают groupBy как замену reduce во всех случаях, не учитывая, что для сложной агрегации reduce гибче
  • Не знают про Map.groupBy для случаев, когда нужны нестроковые ключи или гарантированный порядок

> ГОТОВЫ К СЛЕДУЮЩЕМУ СОБЕСЕДОВАНИЮ?

Запустите тренировочную сессию с ИИ и получите детальную обратную связь, чтобы увереннее проходить реальные интервью