Array Flattening in JavaScript: From Messy Nests to Clean Lists
Nested arrays, .flat(), flatMap(), recursion explained with simple analogies and real examples

CSE student documenting my learning in databases, networking, and web fundamentals.
You've seen those Russian nesting dolls, right? You open one, there's another one inside. You open that one, there's yet another one inside. It's cute as a toy but imagine if your data looked like that.
That's exactly what nested arrays are in JavaScript.
And here's the fun part: almost every real-world JavaScript project will throw nested arrays at you. APIs send them. Databases return them. You accidentally create them.
And when that happens, you'll need to flatten them.
Today, we're going on a journey from messy, deeply nested arrays to clean, flat, easy-to-use lists. By the end of this post, you'll know exactly:
what nested arrays are
why flattening them matters, and
multiple ways to actually do it.
Let's go.
What Are Nested Arrays?
Think of a regular array like a shopping bag. It holds items like this:
const bag = ["apples", "milk", "bread"];
Simple. Clean. One level.
Now imagine you go grocery shopping and bring back multiple bags, and then put all those bags into one big bag:
const groceries = [
["apples", "oranges"], // Bag 1 — fruits
["milk", "cheese"], // Bag 2 — dairy
["bread", "biscuits"] // Bag 3 — bakery
];
That's a nested array, an array that contains other arrays inside it.
And it can go even deeper:
const deeplyNested = [1, [2, 3], [4, [5, [6]]]];
This is the JavaScript equivalent of opening a Russian doll and finding more dolls inside. And more dolls inside those.
Why Is This a Problem?
Alright, so nested arrays exist. But why do we care?
Let's say you get data from an API that looks like this:
const studentScores = [
[85, 90, 78], // Class A
[92, 88, 76], // Class B
[70, 95, 83] // Class C
];
Now you want to find the average score of all students across all classes.
Try doing studentScores.map() or studentScores.reduce() directly on this. Go ahead. I'll wait.
It doesn't work the way you'd expect, does it? Because map and reduce see 3 items (the 3 inner arrays) not 9 individual scores.
You'd have to loop inside a loop, which gets messy fast.
Here's another real-world example. Imagine you're building a search feature. You have categories, and each category has a list of items:
const inventory = [
["shirt", "pants", "jacket"],
["shoes", "socks", "boots"],
["cap", "scarf"]
];
You want to search if "boots" is in inventory. With nested arrays, you'd need to search inside each sub-array. With a flat array, it's just a simple includes().
The core problem: nested arrays make simple operations like searching, summing, mapping, filtering unnecessarily complicated.
The solution: flatten the array first, then do your operation.
The Concept of Flattening
Flattening is simply the process of taking nested arrays and turning them into a single-level array.
Think of it like emptying all those shopping bags onto one table. Instead of bags inside a bag, you just have all items laid out flat:
Take a look at this example code.
BEFORE Flattening:
const arr = [ [1, 2, 3], [4, 5, 6], [7, [8, 9]] ];
AFTER flattening (depth 1):
const arr = [ 1, 2, 3, 4, 5, 6, 7, [8, 9] ]; // 8 and 9 are still nested!
AFTER flattening (depth Infinity):
const arr = [ 1, 2, 3, 4, 5, 6, 7, 8, 9 ]; //everything is out
Now you may be thinking. What is this depth? Let's see.
The key idea here in depth is. How many levels deep do you want to flatten?
depth 1= only open the first layer of bagsdepth 2= open bags inside bagsdepth Infinity= open everything, no matter how deep
Different Approaches to Flatten Arrays
Okay, enough theory. Let's get to the code. There are multiple ways to flatten an array in JavaScript. We'll cover all of them.
Method 1: .flat() The Modern, Easiest Way
Introduced in ES2019, .flat() is the cleanest solution.
Example:
const arr = [1, [2, 3], [4, [5, 6]]];
arr.flat(); // [1, 2, 3, 4, [5, 6]] → depth 1 (default)
arr.flat(2); // [1, 2, 3, 4, 5, 6] → depth 2
arr.flat(Infinity);// [1, 2, 3, 4, 5, 6] → all the way down
When to use it: Almost always. Unless you need to support very old browsers (pre-2019), .flat() is your best friend.
Pro tip: When you don't know how deep the nesting goes, use Infinity:
const messyData = [1, [2, [3, [4, [5]]]]];
console.log(messyData.flat(Infinity));
Output:
[1, 2, 3, 4, 5]
Visual Flow
Method 2: .flatMap() Flatten + Transform in One Step
flatMap() is a combination of .map() and .flat(depth 1) it maps over each element, then flattens the result by one level.
const sentences = ["Hello World", "I love JavaScript"];
sentences.flatMap(sentence => sentence.split(" "));
Output in console:
["Hello", "World", "I", "love", "JavaScript"]
Without flatMap, you'd write:
sentences.map(sentence => sentence.split(" ")).flat();
Output in console:
["Hello", "World", "I", "love", "JavaScript"]
Same result, but two operations instead of one.
When to use it: When you're transforming AND flattening at the same time. Very common in real-world data transformation.
Method 3: reduce() + concat() The Classic Way
Before .flat() existed, developers used reduce with concat.
Example:
const arr = [1, [2, 3], [4, 5]];
arr.reduce((acc, val) => acc.concat(val), []);
Output in console:
[1, 2, 3, 4, 5]
Here's what's happening step by step:
Start with an empty array
[]For each element,
concatit into the accumulatorIf the element is an array,
concatspreads it out
Limitation: This only works for one level of nesting. For deeper nesting, you'd need a recursive version (coming next!).
When to use it: Mostly seen in older codebases. Good to know, but .flat() is preferred today.
Method 4: Recursive Flattening - The Power Move
This is the one that shows up in interviews. What if you need to flatten an array of unknown depth without using .flat()?
Try it out before seeing the solution. I'll wait.
To do this, you write a recursive function:
function flattenDeep(arr) {
return arr.reduce((acc, val) => {
if (Array.isArray(val)) {
// If this element is an array, go deeper!
return acc.concat(flattenDeep(val));
} else {
// If it's a plain value, just add it
return acc.concat(val);
}
}, []);
}
const nested = [1, [2, [3, [4, [5]]]]];
flattenDeep(nested);
Output in console:
[1, 2, 3, 4, 5]
Let's trace through what happens with [1, [2, [3]]]:
Step 1: Look at 1 → not array → add to result: [1]
Step 2: Look at [2,[3]] → IS array → call flattenDeep([2,[3]])
Step 2a: Look at 2 → not array → add to result: [2]
Step 2b: Look at [3] → IS array → call flattenDeep([3])
Step 2b-i: Look at 3 → not array → add to result: [3]
Step 2b: Returns [3]
Step 2: Returns [2, 3]
Final result: [1, 2, 3]
When to use it: In interviews, or when you need fine-grained control
over the flattening logic.
Method 5: Using the Spread Operator
For one level of nesting, there's a neat spread trick.
Example:
const arr = [[1, 2], [3, 4], [5, 6]];
[].concat(...arr);
Output in console:
[1, 2, 3, 4, 5, 6]
When to use it: Quick one-liners for simple, single-depth flattening. Not great for deep nesting.
Quick Comparison Table
| Method | Deep Nesting? | Transforms? | Browser Support | Best For |
|---|---|---|---|---|
.flat() |
✅ (with depth) | ❌ | Modern (ES2019+) | Most cases |
.flatMap() |
❌ (depth 1 only) | ✅ | Modern (ES2019+) | Map + flatten together |
reduce + concat |
❌ (depth 1) | ❌ | All browsers | Older codebases |
| Recursive function | ✅ (unlimited) | ✅ (custom) | All browsers | Interviews, full control |
Spread ... |
❌ (depth 1) | ❌ | All browsers | Quick one-liners |
Summary
Let's lock this in your brain with a quick recap:
Nested arrays = Arrays inside arrays. Like bags inside bags. They exist because real-world data is hierarchical.
Flattening = Taking all those nested values and pulling them out into one single flat array. Depth controls how many levels deep you go.
The 5 ways to flatten:
.flat(depth)→ modern, clean, most common.flatMap(fn)→ map + flatten in one shotreduce + concat→ classic, works everywhereRecursive function → interviews + full control
Spread trick → quick, one level only
The golden rule: If you don't know the depth of nesting → use .flat(Infinity). If you're in an interview without .flat() → write the recursive version.
That's it! Array flattening is one of those concepts that feels confusing at first but clicks the moment you see that "bags inside bags" analogy. The next time your API returns a weirdly nested array, you know exactly what to reach for.
Happy coding!





