How to Flatten Arrays in JavaScript Like a Pro
Flattening arrays is a common task in JavaScript development, especially when dealing with nested structures. In this article, you’ll learn how to implement your own Array.prototype.myFlat
method from scratch—just like the native flat()
—using different techniques.
🔍 What Is Array Flattening?
Flattening means converting a deeply nested array into a single-level array:
js
12
const arr = [0, 1, [2, [3, [4, 5]]]];
// After flattening: [0, 1, 2, 3, 4, 5]
✅ Understanding Native flat()
js
1234
[1, [2, [3]]].flat(2); // [1, 2, 3]
[1, , 2].flat(); // [1, 2]
[1, [2, 3]].flat("2"); // [1, 2, 3]
[1, [2, [3]]].flat(Infinity); // [1, 2, 3]
Key behaviors:
- Doesn’t mutate the original array
- Default depth is
1
- Converts depth to a number (e.g. “2” → 2, NaN → 0)
- Skips empty slots in sparse arrays
📐 ES6 Implementation with Recursion
js
12345678910111213
Array.prototype.myFlat = function (depth = 1) {
const arr = this;
depth = Number.isNaN(+depth) ? 0 : Math.floor(depth);
if (depth < 1) return arr.filter(() => true);
const result = [];
for (let i = 0; i < arr.length; i++) {
if (!Object.hasOwn(arr, i)) continue;
const item = arr[i];
result.push(...(Array.isArray(item) ? item.myFlat(depth - 1) : [item]));
}
return result;
};
🔁 Reduce-Based Functional Version
js
12345678910
Array.prototype.myFlat = function (depth = 1) {
const arr = this;
depth = Number.isNaN(+depth) ? 0 : Math.floor(depth);
if (depth < 1) return arr.filter(() => true);
return arr.reduce((acc, curr, i) => {
if (!Object.hasOwn(arr, i)) return acc;
return acc.concat(Array.isArray(curr) ? curr.myFlat(depth - 1) : [curr]);
}, []);
};
🧱 Stack-Based Iterative Implementation
js
123456789101112131415161718
Array.prototype.myFlat = function (depth = 1) {
const arr = this;
depth = Number.isNaN(+depth) ? 0 : Math.floor(depth);
if (depth < 1) return arr.filter(() => true);
const result = [];
const stack = arr.filter(() => true).map(item => ({ value: item, depth: 1 }));
while (stack.length > 0) {
const { value, depth: d } = stack.pop();
if (Array.isArray(value) && d <= depth) {
stack.push(...value.filter(() => true).map(v => ({ value: v, depth: d + 1 })));
} else {
result.unshift(value);
}
}
return result;
};
✨ Spread-Based Deep Flatten (No Depth Limit)
js
1234567
Array.prototype.myFlat = function () {
let arr = this.filter(() => true);
while (arr.some(item => Array.isArray(item))) {
arr = [].concat(...arr).filter(() => true);
}
return arr;
};
⚠️ Spread version fully flattens the array. No depth control.
🧪 Examples
js
12345
const array = [1, , 2, undefined, [3, [4, [5, 6]]]];
console.log(array.myFlat()); // [1, 2, undefined, 3, [4, [5, 6]]]
console.log(array.myFlat(2)); // [1, 2, undefined, 3, 4, [5, 6]]
console.log(array.myFlat(Infinity)); // [1, 2, undefined, 3, 4, 5, 6]
🧠 Summary
We’ve covered multiple strategies for flattening arrays:
- Recursive with
for
loop - Functional with
reduce
- Iterative with a stack
- Deep flatten using
spread
The recursive approach is readable, but a stack is safer for large depths. Now you can flatten like a pro, with or without .flat()
!