Array Flatten in JavaScript: Everything You Need to Know
Arrays inside arrays inside arrays… sounds fun until you actually have to work with them. Let's fix that.
What Are Nested Arrays?
A normal array looks like this:
const fruits = ["apple", "banana", "mango"];
A nested array is an array that contains other arrays as elements:
const nested = [1, [2, 3], [4, [5, 6]]];
You'll run into nested arrays more often than you think — API responses, grouped data, tree structures, matrix representations. They're everywhere.
Why Flattening Is Useful
Imagine you're building a shopping cart. Each category returns its own array of items:
const electronics = ["laptop", "phone"];
const clothing = ["shirt", "jeans"];
const food = ["rice", "dal"];
const allItems = [electronics, clothing, food];
// [["laptop", "phone"], ["shirt", "jeans"], ["rice", "dal"]]
Now try looping over allItems to render each product — you'll get arrays, not strings. You need a flat list:
// What you want
["laptop", "phone", "shirt", "jeans", "rice", "dal"]
That's exactly what flattening does — it takes a nested array and collapses it into a single-level array.
The Concept: What "Flatten" Really Means
Think of nested arrays like Russian dolls. Flattening is opening each doll and laying everything out on a table.
Input: [1, [2, 3], [4, [5, [6]]]]
Flatten 1 level: [1, 2, 3, 4, [5, [6]]]
Flatten 2 levels: [1, 2, 3, 4, 5, [6]]
Flatten fully: [1, 2, 3, 4, 5, 6]
The depth controls how many levels deep you unwrap.
Approach 1: Array.flat() — The Modern Way
ES2019 introduced Array.flat(). Clean, readable, built-in.
const arr = [1, [2, 3], [4, [5, 6]]];
arr.flat(); // [1, 2, 3, 4, [5, 6]] → default depth is 1
arr.flat(2); // [1, 2, 3, 4, 5, 6] → depth 2
Flatten completely with Infinity
When you don't know how deeply nested the array is:
const deep = [1, [2, [3, [4, [5]]]]];
deep.flat(Infinity); // [1, 2, 3, 4, 5]
It also removes empty slots
const sparse = [1, , 3, [4, , 6]];
sparse.flat(); // [1, 3, 4, 6] ← empty slots removed
When to use: Modern browsers and Node.js 11+. This should be your default choice.
Approach 2: reduce() + concat() — The Classic
Before .flat() existed, this was the go-to pattern. You'll see it in interviews a lot.
Flatten one level deep
function flattenOne(arr) {
return arr.reduce((acc, val) => acc.concat(val), []);
}
flattenOne([1, [2, 3], [4, 5]]); // [1, 2, 3, 4, 5]
Step by step:
Start: acc = []
Iteration 1: acc = [].concat(1) → [1]
Iteration 2: acc = [1].concat([2,3]) → [1, 2, 3]
Iteration 3: acc = [1,2,3].concat([4,5]) → [1, 2, 3, 4, 5]
Flatten recursively (any depth)
function flattenDeep(arr) {
return arr.reduce((acc, val) =>
Array.isArray(val)
? acc.concat(flattenDeep(val)) // recurse if it's an array
: acc.concat(val), // otherwise just add it
[]);
}
flattenDeep([1, [2, [3, [4]]]]); // [1, 2, 3, 4]
Approach 3: Spread + concat() — One-liner
const arr = [1, [2, 3], [4, 5]];
[].concat(...arr); // [1, 2, 3, 4, 5]
This only works for one level. Using ...arr spreads the outer array as arguments to concat, which handles the inner arrays.
⚠️ Breaks with deeply nested arrays or very large arrays (hits argument limit).
Approach 4: Manual Recursion — Best for Interviews
Writing your own flatten from scratch is the most common interview question. Know this cold.
function flatten(arr, depth = Infinity) {
const result = [];
for (const item of arr) {
if (Array.isArray(item) && depth > 0) {
// it's an array — go deeper
result.push(...flatten(item, depth - 1));
} else {
// it's a value — add it
result.push(item);
}
}
return result;
}
flatten([1, [2, [3, [4]]]]); // [1, 2, 3, 4] ← full depth
flatten([1, [2, [3, [4]]]], 1); // [1, 2, [3, [4]]] ← 1 level
flatten([1, [2, [3, [4]]]], 2); // [1, 2, 3, [4]] ← 2 levels
Approach 5: Stack-Based (No Recursion)
Recursion can hit the call stack limit with deeply nested arrays. A stack-based approach avoids that:
function flattenIterative(arr) {
const stack = [...arr];
const result = [];
while (stack.length) {
const item = stack.pop();
if (Array.isArray(item)) {
stack.push(...item); // push children back onto the stack
} else {
result.unshift(item); // add value to front (preserves order)
}
}
return result;
}
flattenIterative([1, [2, [3, [4, 5]]]]); // [1, 2, 3, 4, 5]
This is great to mention in interviews when the interviewer asks "what if the input is extremely deeply nested?"
Common Interview Scenarios
Q1: Flatten only one level
// Input: [1, [2, 3], [4, [5]]]
// Output: [1, 2, 3, 4, [5]]
arr.flat(); // built-in
arr.reduce((a, v) => a.concat(v), []); // manual
Q2: Flatten completely
// Input: [1, [2, [3, [4, [5]]]]]
// Output: [1, 2, 3, 4, 5]
arr.flat(Infinity); // built-in
flattenDeep(arr); // recursive
Q3: Flatten and then remove duplicates
const arr = [[1, 2], [2, 3], [3, 4]];
const result = [...new Set(arr.flat())];
// [1, 2, 3, 4]
Q4: Flatten an array of objects' nested arrays
const data = [
{ id: 1, tags: ["js", "node"] },
{ id: 2, tags: ["react", "js"] },
];
const allTags = data.map(item => item.tags).flat();
// ["js", "node", "react", "js"]
// Or using flatMap (map + flat in one step):
const allTags2 = data.flatMap(item => item.tags);
// ["js", "node", "react", "js"]
Q5: Count total elements after flattening (without flattening)
function countElements(arr) {
return arr.reduce((count, item) =>
Array.isArray(item) ? count + countElements(item) : count + 1
, 0);
}
countElements([1, [2, [3, 4]], 5]); // 5
Quick Tip: flatMap() — Map and Flatten Together
flatMap() is equivalent to .map().flat(1) — super useful when your map callback returns arrays:
const sentences = ["Hello World", "JavaScript is fun"];
// Without flatMap
sentences.map(s => s.split(" ")).flat();
// ["Hello", "World", "JavaScript", "is", "fun"]
// With flatMap
sentences.flatMap(s => s.split(" "));
// ["Hello", "World", "JavaScript", "is", "fun"]
When to Use What
| Situation | Best Choice |
|---|---|
| Modern codebase, any depth | arr.flat(Infinity) |
| Specific depth needed | arr.flat(n) |
| Map + flatten in one step | arr.flatMap() |
| Interview, write from scratch | Recursive flatten() |
| Extremely deep nesting | Stack-based iterative |
| Legacy code / no ES2019 | reduce() + concat() |
Summary
Flattening arrays is about collapsing nested structure into a single level. JavaScript gives you .flat() for everyday use, but knowing how to implement it manually — recursively or iteratively — is what separates a good developer from a great one.
The next time you see [[1,2],[3,4]] in an API response, you'll know exactly what to do. 🧩
Found this useful? Share it with someone grinding LeetCode or preparing for their next JavaScript interview. 🚀

