Array.prototype.flatMap()
BaselineWidely available
This feature is well established and works across many devices and browser versions. It’s been available across browsers since January 2020.
TheflatMap()
method ofArray
instances returns a new array formed by applying a given callback function to each element of the array, and then flattening the result by one level. It is identical to amap()
followed by aflat()
of depth 1 (arr.map(...args).flat()
), but slightly more efficient than calling those two methods separately.
Try it
const arr1 = [1, 2, 1];const result = arr1.flatMap((num) => (num === 2 ? [2, 2] : 1));console.log(result);// Expected output: Array [1, 2, 2, 1]
Syntax
flatMap(callbackFn)flatMap(callbackFn, thisArg)
Parameters
callbackFn
A function to execute for each element in the array. It should return an array containing new elements of the new array, or a single non-array value to be added to the new array. The function is called with the following arguments:
thisArg
OptionalA value to use as
this
when executingcallbackFn
. Seeiterative methods.
Return value
A new array with each element being the result of the callback function and flattenedby a depth of 1.
Description
TheflatMap()
method is aniterative method. SeeArray.prototype.map()
for a detailed description of the callback function. TheflatMap()
method is identical tomap(callbackFn, thisArg)
followed byflat(1)
— for each element, it produces an array of new elements, and concatenates the resulting arrays together to form a new array. Read theiterative methods section for more information about how these methods work in general.
TheflatMap()
method isgeneric. It only expects thethis
value to have alength
property and integer-keyed properties. However, the value returned fromcallbackFn
must be an array if it is to be flattened.
Alternative
Pre-allocate and explicitly iterate
const arr = [1, 2, 3, 4];arr.flatMap((x) => [x, x * 2]);// is equivalent toconst 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]
Note that in this particular case theflatMap
approach is slower than thefor-loop approach — due to the creation of temporary arrays that must begarbage collected, as well as the return array not needing to be frequentlyresized. However,flatMap
may still be the correct solution in cases whereits flexibility and readability are desired.
Examples
map() and flatMap()
const arr1 = [1, 2, 3, 4];arr1.map((x) => [x * 2]);// [[2], [4], [6], [8]]arr1.flatMap((x) => [x * 2]);// [2, 4, 6, 8]// only one level is flattenedarr1.flatMap((x) => [[x * 2]]);// [[2], [4], [6], [8]]
While the above could have been achieved by using map itself, here is an example thatbetter showcases the use offlatMap()
.
Let's generate a list of words from a list of sentences.
const arr1 = ["it's Sunny in", "", "California"];arr1.map((x) => x.split(" "));// [["it's","Sunny","in"],[""],["California"]]arr1.flatMap((x) => x.split(" "));// ["it's","Sunny","in", "", "California"]
Notice, the output list length can be different from the input list length.
For adding and removing items during a map()
flatMap
can be used as a way to add and remove items (modify the number ofitems) during amap
. In other words, it allows you to mapmany items tomany items (by handling each input item separately), rather than alwaysone-to-one. In this sense, it works like the opposite offilter.Return a 1-element array to keep the item, a multiple-element array to add items, or a0-element array to remove the item.
// Let's say we want to remove all the negative numbers// and split the odd numbers into an even number and a 1const 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]
Using the third argument of callbackFn
Thearray
argument is useful if you want to access another element in the array, especially when you don't have an existing variable that refers to the array. The following example first usesfilter()
to extract operational stations and then usesflatMap()
to create a new array where each element contains a station and its next station. On the last station, it returns an empty array to exclude it from the final array.
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']
Thearray
argument isnot the array that is being built — there is no way to access the array being built from the callback function.
Using flatMap() on sparse arrays
ThecallbackFn
won't be called for empty slots in the source array becausemap()
doesn't, whileflat()
ignores empty slots in the returned arrays.
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]
Calling flatMap() on non-array objects
TheflatMap()
method reads thelength
property ofthis
and then accesses each property whose key is a nonnegative integer less thanlength
. If the return value of the callback function is not an array, it is always directly appended to the result array.
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 flattenedconsole.log( Array.prototype.flatMap.call(arrayLike, (x) => ({ length: 1, 0: x, })),);// [ { '0': 1, length: 1 }, { '0': 2, length: 1 }, { '0': 3, length: 1 } ]
Specifications
Specification |
---|
ECMAScript® 2026 Language Specification # sec-array.prototype.flatmap |