, ,

How to Flatten Deeply Nested Arrays in JavaScript

Posted by

From simple recursion to powerful ES2025 tricks

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

Your email address will not be published. Required fields are marked *