
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.

The flat() and flatMap() methods
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
Aug 11, 2026

Vapor Mode in Practice
A hands-on look at opting individual components into Vue 3.6 Vapor Mode, where it helps, and the real limitations as of mid-2026.
Reza Baar
Aug 5, 2026

The First Hands-On AI Developer Certification
Discover how the AI Developer Certification measures real-world AI-assisted development through a hands-on, proctored exam. Learn what makes the certification unique, how it works, and what to expect when preorders open.
Alex Garrett-Smith
Jul 23, 2026