Что такое Array.flat и flatMap в JavaScript?
Array.flat(depth) создаёт новый массив, разворачивая вложенные подмассивы на указанную глубину. Array.flatMap(fn) применяет функцию к каждому элементу и разворачивает результат на один уровень — это эффективная замена map().flat(1).Array.flat
Метод Array.flat() создаёт новый массив, объединяя все вложенные подмассивы в один. Принимает необязательный параметр depth, определяющий глубину разворачивания (по умолчанию 1).
Основные особенности
- Создаёт новый массив, не мутирует исходный.
- Пустые ячейки (
holes) в разреженных массивах удаляются. - Передача
Infinityразворачивает массив любой глубины вложенности.
const arr = [1, [2, [3, [4]]]];
arr.flat(); // [1, 2, [3, [4]]] — глубина 1 по умолчанию
arr.flat(2); // [1, 2, 3, [4]]
arr.flat(Infinity); // [1, 2, 3, 4]
// Разреженные массивы — дыры удаляются
[1, , 2, , 3].flat(); // [1, 2, 3]
Array.flatMap
Метод Array.flatMap() сначала применяет функцию-маппер к каждому элементу, а затем разворачивает результат ровно на один уровень. Семантически эквивалентен arr.map(...).flat(1), но работает за один проход — это делает его более эффективным по памяти и производительности.
const sentences = ['Hello world', 'foo bar'];
// Без flatMap — два прохода
sentences.map(s => s.split(' ')).flat();
// ['Hello', 'world', 'foo', 'bar']
// С flatMap — один проход, результат идентичен
sentences.flatMap(s => s.split(' '));
// ['Hello', 'world', 'foo', 'bar']
Фильтрация через flatMap
Один из паттернов — возвращать пустой массив для элементов, которые нужно пропустить. Это совмещает маппинг и фильтрацию в одной операции.
const numbers = [1, 2, 3, 4, 5];
// Удваиваем чётные числа, нечётные пропускаем
const result = numbers.flatMap(n => n % 2 === 0 ? [n, n * 2] : []);
// [2, 4, 4, 8]
flat vs flatMap — ключевые отличия
flat | flatMap | |
|---|---|---|
| Аргумент | глубина (число) | функция-маппер |
| Глубина разворачивания | любая | всегда 1 |
| Назначение | только разворачивание | трансформация + разворачивание |
Поддержка и полифил
Оба метода появились в ES2019 (ES10) и поддерживаются во всех современных браузерах. Для устаревших окружений используют полифил через reduce:
// Полифил flat(1)
const flatten = arr => arr.reduce((acc, val) => acc.concat(val), []);
// Полифил flatMap
const flatMap = (arr, fn) => arr.reduce((acc, val, i) => acc.concat(fn(val, i, arr)), []);
Что хочет услышать интервьюер
Понимание разницы между flat и flatMap: flat только разворачивает, flatMap сначала преобразует, потом разворачивает
Знание параметра depth у flat и того, что flatMap всегда разворачивает только на 1 уровень
Понимание, что оба метода не мутируют исходный массив и возвращают новый
Осознание практической пользы flatMap — один проход вместо map().flat(1), паттерн фильтрации через пустой массив
Знание версии ES, в которой появились методы (ES2019), и наличие полифилов
Пример: flat — разворачивание вложенных массивов
const nested: number[][][] = [[[1, 2]], [[3, 4]], [[5]]];
// Глубина 1 — разворачивает один уровень
nested.flat();
// [[1, 2], [3, 4], [5]]
// Глубина 2 — разворачивает до плоского массива
nested.flat(2);
// [1, 2, 3, 4, 5]
// Произвольная вложенность
const deep = [1, [2, [3, [4, [5]]]]];
deep.flat(Infinity);
// [1, 2, 3, 4, 5]
Пример: flatMap — трансформация и разворачивание
// Разбиваем предложения на слова
const phrases: string[] = ['apple orange', 'foo bar baz'];
const words = phrases.flatMap(phrase => phrase.split(' '));
// ['apple', 'orange', 'foo', 'bar', 'baz']
// Паттерн: map + filter за один проход
const orders: Array<{ id: number; items: string[] }> = [
{ id: 1, items: ['book', 'pen'] },
{ id: 2, items: [] }, // пустой заказ
{ id: 3, items: ['notebook'] },
];
// Получаем все товары, игнорируя пустые заказы
const allItems = orders.flatMap(order =>
order.items.length > 0 ? order.items : []
);
// ['book', 'pen', 'notebook']
Типичные ошибки
Считают, что flatMap разворачивает на произвольную глубину — он всегда разворачивает только на 1 уровень
Забывают передать depth в flat при глубокой вложенности и удивляются неполному результату
Путают порядок операций в flatMap: сначала map, потом flat — а не наоборот
Не знают о паттерне фильтрации через пустой массив [] в flatMap
Не помнят, что flat удаляет дыры в разреженных массивах (sparse arrays)


