From simple recursion to powerful ES2025 tricks

Introduction
You’ve probably run into this before:
const nested = [1, [2, [3, [4, 5]]]];
Now you want:
[1, 2, 3, 4, 5]
Flattening arrays sounds trivial… until you see the many ways to do it in JavaScript. Should you use recursion? reduce
? A built-in method like .flat()
? Or go fancy with generators?
This article covers all the major patterns for flattening deeply nested arrays, with pros, cons, performance notes, and real-world use cases.
1) Quick Win: Array.prototype.flat
Since ES2019, we’ve had flat()
:
const nested = [1, [2, [3, [4, 5]]]];
const flat = nested.flat(Infinity);
console.log(flat); // [1, 2, 3, 4, 5]
flat(depth)
flattens up to the given depth.- Pass
Infinity
to flatten all the way down.
👉 Best choice when you can target modern runtimes.
2) Recursion (Classic Vanilla Approach)
Before flat
, recursion was the go-to:
function flatten(arr) {
let result = [];
for (const el of arr) {
if (Array.isArray(el)) {
result = result.concat(flatten(el));
} else {
result.push(el);
}
}
return result;
}
console.log(flatten([1, [2, [3, [4, 5]]]])); // [1, 2, 3, 4, 5]
- Straightforward, works everywhere.
- Handles arbitrarily deep nesting.
- But concatenating arrays repeatedly can be slower for very large datasets.
3) Iterative Approach with a Stack
If recursion depth is a concern (e.g., extremely deep arrays), simulate recursion with a stack:
function flatten(arr) {
const stack = [...arr];
const result = [];
while (stack.length) {
const next = stack.pop();
if (Array.isArray(next)) {
stack.push(...next); // expand array into stack
} else {
result.push(next);
}
}
return result.reverse(); // reverse because stack reverses order
}
console.log(flatten([1, [2, [3, [4, 5]]]])); // [1, 2, 3, 4, 5]
- Avoids recursion depth issues.
- Can handle massive nesting safely.
4) Reduce + Recursion (Functional Style)
More declarative:
const flatten = arr =>
arr.reduce((acc, val) =>
Array.isArray(val) ? acc.concat(flatten(val)) : acc.concat(val), []
);
console.log(flatten([1, [2, [3, [4, 5]]]]));
- One-liner elegance.
- Still recursive.
- Easy to combine with functional pipelines.
5) Generator-Based Flattening
Generators let you flatten lazily:
function* flattenGen(arr) {
for (const el of arr) {
if (Array.isArray(el)) {
yield* flattenGen(el); // delegate recursion
} else {
yield el;
}
}
}
const nested = [1, [2, [3, [4, 5]]]];
console.log([...flattenGen(nested)]); // [1, 2, 3, 4, 5]
- Doesn’t build the full result immediately — great for streaming or partial consumption.
- Memory efficient for huge arrays.
6) FlatMap (Shallow, but Useful)
flatMap
flattens only one level, but it’s useful for structured transforms:
const arr = ["hello world", "foo bar"];
const words = arr.flatMap(str => str.split(" "));
console.log(words); // ["hello", "world", "foo", "bar"]
- Perfect for “split and flatten” use cases.
- Not a deep-flattening solution.
7) Typed Arrays & Performance Hacks
For very large arrays (millions of elements):
- Prefer
.flat(Infinity)
→ optimized in most engines. - Or iterative stack-based flattening.
- Avoid repeated
concat
inside loops—it reallocates arrays. Instead, push into a single result array.
8) Handling Non-Array-Like Data
Sometimes “nested arrays” aren’t just arrays — they might be array-like (NodeLists, Sets). Normalize first:
function toArray(val) {
return Array.isArray(val) ? val : Array.from(val);
}
Then flatten as usual.
9) Real-World Use Cases
a) API Responses
const apiData = [[{id:1}], [{id:2}, {id:3}]];
const flat = apiData.flat();
b) UI Rendering
Flattening nested React children arrays before mapping to DOM nodes.
c) Data Transform Pipelines
Parsing CSVs, logs, or nested JSON into flat lists for analysis.
10) Quick Reference Table

Conclusion
Flattening arrays in JavaScript has gone from tricky recursion hacks to one-liners with flat(Infinity)
. But it’s still useful to know the patterns:
- Use
.flat(Infinity)
in modern code. - Use recursion or stack-based iteration if you need ES5 compatibility.
- Use generators for lazy flattening on big data.
- Remember:
flatMap
is for shallow transforms, not deep flattening.
Pro tip: Always measure with large datasets — .flat(Infinity)
is fast, but iterative stack flattening may win for extreme nesting.
Call to Action
Which method do you use most — flat(Infinity)
or recursion?
💬 Share your go-to snippet in the comments.
🔖 Bookmark this as your flattening toolbox.
👩💻 Share with a teammate still writing nested reduce
chains.
Leave a Reply