Spec-Zone.ru › JavaScript

Array.prototype.flatMap()

Базовый уровень Широко доступен

Эта функция хорошо зарекомендовала себя и работает на многих устройствах и в различных версиях браузеров. Она доступна во всех браузерах с января 2020 года.

Метод flatMap() экземпляров Array возвращает новый массив, сформированный путем применения заданной функции обратного вызова к каждому элементу массива, а затем сглаживания результата на один уровень. Он идентичен вызову map() с последующим вызовом flat() с глубиной 1 (arr.map(...args).flat()), но немного более эффективен, чем вызов этих двух методов по отдельности.

Попробуйте

const arr = [1, 2, 1];

const result = arr.flatMap((num) => (num === 2 ? [2, 2] : 1));

console.log(result);
// Expected output: Array [1, 2, 2, 1]

Синтаксис

flatMap(callbackFn)
flatMap(callbackFn, thisArg)

Параметры

callbackFn
Функция, которая будет выполняться для каждого элемента в массиве. Она должна возвращать массив, содержащий новые элементы для нового массива, или одно значение, не являющееся массивом, которое будет добавлено в новый массив. Функция вызывается со следующими аргументами:
element
Текущий обрабатываемый элемент в массиве.
index
Индекс текущего обрабатываемого элемента в массиве.
array
Массив, к которому был применён flatMap().
thisArg Необязательно
Значение, используемое в качестве this при выполнении callbackFn. См. итеративные методы.

Возвращаемое значение

Новый массив, каждый элемент которого является результатом функции обратного вызова и который сглажен на глубину 1.

Описание

Метод flatMap() является итеративным методом. См. Array.prototype.map() для подробного описания функции обратного вызова. Метод flatMap() идентичен вызову map(callbackFn, thisArg) с последующим вызовом flat(1) — для каждого элемента он создает массив новых элементов и объединяет (конкатенирует) полученные массивы для формирования нового массива. Прочтите раздел итеративные методы для получения дополнительной информации о том, как эти методы работают в целом.

Метод flatMap() является обобщенным. Он ожидает, что значение this будет иметь свойство length и свойства с целочисленными ключами. Однако, значение, возвращаемое из callbackFn, должно быть массивом, если его нужно сглаживать.

Альтернатива

Предварительное выделение памяти и явная итерация

const arr = [1, 2, 3, 4];

arr.flatMap((x) => [x, x * 2]);
// is equivalent to
const n = arr.length;
const acc = new Array(n * 2);
for (let i = 0; i < n; i++) {
  const x = arr[i];
  acc[i * 2] = x;
  acc[i * 2 + 1] = x * 2;
}
// [1, 2, 2, 4, 3, 6, 4, 8]

Обратите внимание, что в данном конкретном случае подход flatMap медленнее, чем подход с циклом for — из-за создания временных массивов, которые должны быть очищены сборщиком мусора, а также из-за того, что размер возвращаемого массива не нужно часто изменять. Однако, flatMap все равно может быть правильным решением в тех случаях, когда важна его гибкость и читаемость.

Примеры

map() and flatMap()

const arr = [1, 2, 3, 4];

arr.map((x) => [x * 2]);
// [[2], [4], [6], [8]]

arr.flatMap((x) => [x * 2]);
// [2, 4, 6, 8]

// only one level is flattened
arr.flatMap((x) => [[x * 2]]);
// [[2], [4], [6], [8]]

Хотя вышеуказанное могло быть достигнуто с помощью map, вот пример, который лучше демонстрирует использование flatMap().

Давайте сгенерируем список слов из списка предложений.

const arr = ["it's Sunny in", "", "California"];

arr.map((x) => x.split(" "));
// [["it's","Sunny","in"],[""],["California"]]

arr.flatMap((x) => x.split(" "));
// ["it's","Sunny","in", "", "California"]

Обратите внимание, длина выходного списка может отличаться от длины входного списка.

Для добавления и удаления элементов во время map()

flatMap можно использовать как способ добавления и удаления элементов (изменения количества элементов) во время map. Другими словами, он позволяет отображать много элементов во много элементов (путем отдельной обработки каждого входного элемента), а не всегда один к одному. В этом смысле он работает как противоположность filter. Верните массив из 1 элемента, чтобы сохранить элемент, массив из нескольких элементов, чтобы добавить элементы, или массив из 0 элементов, чтобы удалить элемент.

// Let's say we want to remove all the negative numbers
// and split the odd numbers into an even number and a 1
const a = [5, 4, -3, 20, 17, -33, -4, 18];
//         |\  \  x   |  | \   x   x   |
//        [4,1, 4,   20, 16, 1,       18]

const result = a.flatMap((n) => {
  if (n < 0) {
    return [];
  }
  return n % 2 === 0 ? [n] : [n - 1, 1];
});
console.log(result); // [4, 1, 4, 20, 16, 1, 18]

Использование третьего аргумента callbackFn

Аргумент array полезен, если вы хотите получить доступ к другому элементу в массиве, особенно если у вас нет существующей переменной, ссылающейся на массив. Следующий пример сначала использует filter() для извлечения работающих станций, а затем использует flatMap() для создания нового массива, где каждый элемент содержит станцию и ее следующую станцию. На последней станции он возвращает пустой массив, чтобы исключить ее из конечного массива.

const stations = ["New Haven", "West Haven", "Milford (closed)", "Stratford"];
const line = stations
  .filter((name) => !name.endsWith("(closed)"))
  .flatMap((name, idx, arr) => {
    // Without the arr argument, there's no way to easily access the
    // intermediate array without saving it to a variable.
    if (idx === arr.length - 1) return []; // last station has no next station
    return [`${name} - ${arr[idx + 1]}`];
  });
console.log(line); // ['New Haven - West Haven', 'West Haven - Stratford']

Аргумент array не является массивом, который строится — нет способа получить доступ к строящемуся массиву из функции обратного вызова.

Использование flatMap() на разреженных массивах

callbackFn не будет вызываться для пустых слотов в исходном массиве, поскольку map() этого не делает, в то время как flat() игнорирует пустые слоты в возвращаемых массивах.

console.log([1, 2, , 4, 5].flatMap((x) => [x, x * 2])); // [1, 2, 2, 4, 4, 8, 5, 10]
console.log([1, 2, 3, 4].flatMap((x) => [, x * 2])); // [2, 4, 6, 8]

Вызов flatMap() для объектов, не являющихся массивами

Метод flatMap() считывает свойство length объекта this, а затем обращается к каждому свойству, ключ которого является неотрицательным целым числом, меньшим, чем length. Если возвращаемое значение функции обратного вызова не является массивом, оно всегда напрямую добавляется в результирующий массив.

const arrayLike = {
  length: 3,
  0: 1,
  1: 2,
  2: 3,
  3: 4, // ignored by flatMap() since length is 3
};
console.log(Array.prototype.flatMap.call(arrayLike, (x) => [x, x * 2]));
// [1, 2, 2, 4, 3, 6]

// Array-like objects returned from the callback won't be flattened
console.log(
  Array.prototype.flatMap.call(arrayLike, (x) => ({
    length: 1,
    0: x,
  })),
);
// [ { '0': 1, length: 1 }, { '0': 2, length: 1 }, { '0': 3, length: 1 } ]

Спецификации

Specification
ECMAScript® 2027 Language Specification
# sec-array.prototype.flatmap

Совместимость с браузерами

Рабочий стол Мобильные устройства Сервер
Chrome Edge Firefox Opera Safari Chrome Android Firefox for Android Opera Android Safari on iOS Samsung Internet WebView Android WebView on iOS Bun Deno Node.js
flatMap
69
79
62
56
12
69
62
48
12
10.0
69
12
1.0.0
1.0
11.0.0

См. также

  • Полифилл Array.prototype.flatMap в core-js
  • Полифилл Array.prototype.flatMap от es-shims
  • Руководство по Indexed collections
  • Array
  • Array.prototype.concat()
  • Array.prototype.flat()
  • Array.prototype.map()
  • Array.prototype.reduce()

© 2005–2025 MDN contributors.
Licensed under the Creative Commons Attribution-ShareAlike License v2.5 or later.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/flatMap

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API