The Developer's Guide to Flattening Arrays in JavaScript
Stop Wrestling Nested Data

Let us see the problem first. Imagine you fetched user data from two API pages. Page one gives you [1, 2, 3]. Page two gives you [4, 5, 6]. You shove them both into an array to combine them, and you get this:
const page1 = [1, 2, 3];
const page2 = [4, 5, 6];
const combined = [page1, page2];
console.log(combined);
// → [[1, 2, 3], [4, 5, 6]] | not what you wanted
// You wanted [1, 2, 3, 4, 5, 6]
// What you got is an array of arrays
That outer wrapper is the problem. You don't want to loop over two arrays, you want one flat list. That's flattening. You're collapsing the layers down into a single level so you can actually work with the data.
This happens more than you'd think. APIs send paginated responses. A .map() that returns an array per item gives you nested output. Form inputs grouped by section produce grouped values. The data structure that made sense to build becomes inconvenient the moment you need to use it.
What Nested Actually Looks Like
Before getting into solutions, it's worth seeing exactly what we're dealing with. An array can nest multiple levels deep, each layer adds another set of brackets around the values inside.
The number of layers is called depth. Depth 1 means one array wrapped inside another. Depth 2 means arrays inside arrays inside the outer array. When you flatten, you're deciding how many of those layers to remove.
Just Use .flat()
ES2019 added Array.prototype.flat() and honestly it just works. Pass a depth number, or pass Infinity to collapse every layer no matter how deep. Most of the time this is all you need.
const nested = [1, [2, 3], [4, [5, 6]]];
nested.flat();
// [1, 2, 3, 4, [5, 6]] default depth is 1
nested.flat(2);
// [1, 2, 3, 4, 5, 6] removes two levels
nested.flat(Infinity);
// [1, 2, 3, 4, 5, 6] flattens everything
There's also .flatMap(), which runs a map and flattens one level in one pass. It's faster than calling .map() then .flat(1) separately, and you'll use it whenever your mapping function returns an array per element.
const sentences = ["hello world", "foo bar"];
// .map() gives you nested arrays
sentences.map(s => s.split(" "));
// [["hello","world"], ["foo","bar"]]
// .flatMap() flattens that one level automatically
sentences.flatMap(s => s.split(" "));
// ["hello", "world", "foo", "bar"]
One thing to watch:
.flat()skips empty slots in arrays , things like[1, , 3]. That's usually what you want, but if you're working with sparse arrays intentionally, keep it in mind.
Before .flat() Came to Existence
This might be a favourite topic of few interviewers out there, to flatten the array without the inbuilt method. The classic approach uses reduce with recursion. For each element, check if it's an array. If it is, flatten it recursively and concat the result. If it isn't, add it directly.
function flatten(arr) {
return arr.reduce((acc, val) =>
Array.isArray(val) ? acc.concat(flatten(val)) : acc.concat(val),
[]);
}
flatten([1, [2, [3, [4, [5]]]]]);
// [1, 2, 3, 4, 5]
// works at any depth
This handles any depth without you specifying it. The recursion bottoms out naturally when there are no more arrays to unwrap.
For the depth-controlled version, that's a small addition:
const flattenByDepth = (arr, depth = 1) =>
depth > 0 ? arr.reduce((acc, val) =>
acc.concat(Array.isArray(val) ? flattenByDepth(val, depth - 1) : val),
[]) : arr.slice();
flattenDepth([1, [2, [3, [4]]]], 2);
// [1, 2, 3, [4]]
// stopped at depth 2
Nested arrays happen. APIs return batches, maps produce nested output, data gets grouped before it gets used. Flattening is just the act of removing those layers. .flat(Infinity) handles it in one call. The recursive reduce version is what interviewers want you to derive. And once you've written flatten a few times, the same mental model carries over to nested objects, tree traversal, and anything else where data lives at multiple depths.
The depth question is the one to keep in mind. Most bugs with flattening come from not removing enough layers, or accidentally removing too many. Know what's in your data before you pick your depth.
REFERENCES:




