
Learn how JavaScript's flat() and flatMap() work: default depth, flat(Infinity), dropping holes, and using flatMap as a combined map and filter.
Martin Ferret
August 11, 2026
For a long time, flattening a nested array in JavaScript meant reaching for a loop or a reduce. The flat() and flatMap() methods, introduced in ES2019, cover that need in a way that is readable and direct.
flat() creates a new array with all sub-array elements pulled up by one or more levels. By default, it only pulls up a single level.
const nested = [1, [2, 3], [4, 5]];
const flat = nested.flat();
console.log(flat); // → [1, 2, 3, 4, 5]
Read it as: "lift the elements of the sub-arrays up by one level."
flat() With No Argument Is Not EnoughBy default, flat() only descends one level. As soon as the structure is nested deeper than that, the result surprises you.
const deep = [1, [2, [3, [4]]]];
deep.flat(); // → [1, 2, [3, [4]]] only one level removed
deep.flat(2); // → [1, 2, 3, [4]]
deep.flat(Infinity); // → [1, 2, 3, 4] flattens every level, whatever the depth
The mental model: flat() asks "how many levels should I go down?", and the default answer is: just one.
| Call | Behavior |
|---|---|
flat() | depth of 1 (the default) |
flat(2) | descends 2 levels |
flat(Infinity) | flattens the entire depth, however deep |
flat(0) | changes nothing, returns a shallow copy |
flat() also drops the empty slots (holes) of a sparse array as it goes, something map() does not do.
const sparse = [1, , 3, [4, , 6]];
console.log(sparse.flat()); // → [1, 3, 4, 6] the holes are gone
Sometimes that is exactly what you want, and sometimes it is a surprise: worth keeping in mind if the array can contain holes.
flatMap(): Map, Then FlattenflatMap() combines map() and flat() in a single pass: it applies a function to each element, then flattens the result by one level.
const numbers = [1, 2, 3];
const result = numbers.flatMap(n => [n, n * 2]);
console.log(result); // → [1, 2, 2, 4, 3, 6]
With map() alone, you would get an array of arrays that you then have to flatten yourself:
numbers.map(n => [n, n * 2]);
// → [[1, 2], [2, 4], [3, 6]]
In other words, arr.flatMap(fn) is identical to arr.map(fn).flat() (a flat() of depth 1), but slightly more efficient than calling the two methods separately, since it does not build a full intermediate array of arrays.
flatMap() as map and filter CombinedBecause the callback can return an array of any length, returning [] drops the element and returning several values adds them. That turns flatMap() into a combined map and filter.
const values = [5, -2, 8, -1, 3];
// Keep the positives, double them, and drop the negatives
const positives = values.flatMap(n => n > 0 ? [n * 2] : []);
console.log(positives); // → [10, 16, 6]
This is a common idiom: where a filter followed by a map needed two passes, flatMap does the filtering and the transforming in a single expression. Like map(), it also skips holes in a sparse array.
💡
flatMap()only flattens one level, and that level is not configurable: there is noflatMap(fn, depth). If the callback returns arrays nested more than one level deep, chain aflat()afterward:arr.flatMap(fn).flat(Infinity). This is deliberate:flatMapis built for the common one-to-many case, not for deep flattening.
[1, 2].flatMap(n => [[n]]);
// → [[1], [2]] only one level removed, the inner arrays remain
flat() and flatMap() replace verbose loops and reduce calls with two readable methods. Use flat() to level out a structure you have already built, with Infinity when the depth is unknown. Use flatMap() to transform and flatten in a single pass, where it shines whenever each element produces zero, one, or several values.
In any code that builds lists out of other lists, these two methods make intent explicit, and intent is what separates readable code from clever code.
Get the latest news and updates on developer certifications. Content is updated regularly, so please make sure to bookmark this page or sign up to get the latest content directly in your inbox.

Building a Vue Career in the Age of AI Coding Tools
How Junior Vue Developers Can Get Hired in 2026 and and what companies are looking for
Reza Baar
Aug 12, 2026

How YouTube Works, and Why It Plays in One Second
How does YouTube start almost any video in about a second? Here's the architectural bet behind it, and why the real call still belongs to you.
Alex Garrett-Smith
Aug 12, 2026

Nuxt 3 hits End Of Life
Nuxt 3 Hits EOL July 31, 2026: Your Staged Path to Nuxt 5 What the Nuxt 3 end-of-life date means, how to migrate through Nuxt 4, and when it makes sense to wait for Nuxt 5 instead.
Reza Baar
Aug 12, 2026