DEV Community

Cover image for Mastering Array Flattening in JavaScript: From Nested Chaos to Clean Lists
Ritam Saha
Ritam Saha

Posted on

Mastering Array Flattening in JavaScript: From Nested Chaos to Clean Lists

Imagine you're building a shopping cart app. Users add items like ["apple", "banana", ["orange", ["grape", "kiwi"]]]. Suddenly, your loops break because of those sneaky nested arrays. Frustrating, right?
Array flattening turns this mess into a simple ["apple", "banana", "orange", "grape", "kiwi"]. In this blog, we'll demystify nested arrays, explore why flattening matters, break down approaches step-by-step, and tackle real interview scenarios—including a custom polyfill you can steal (or improve).


What Are Nested Arrays?

Nested arrays are arrays containing other arrays as elements within it.

Original Nested Array:
[
  1,
  [2, 3],
  [4, [5, 6], 7],
  8
]
Enter fullscreen mode Exit fullscreen mode

Think of it like a filing cabinet: top-level folders hold documents and sub-folders.


Why Flatten Arrays win in Real-world scenarios?

Flattening simplifies data for:

  • Iteration: Loop once without if (Array.isArray(item)) checks.
  • Processing: Easier sorting, filtering, or mapping on flat lists.
  • UI Rendering: Display cart items or file trees linearly.
  • Performance: Reduces recursion depth in algorithms.

Example: Flattening [1, [2,3], 4] will let array.map(x => x*2) over the flatten array yield [2,4,6,8] cleanly.


The Flattening Concept: Step-by-Step

Flattening extracts all elements into a single-level array. Key decisions:

  1. Copy: Shallow vs. deep
  2. Depth control: Stop at a max depth to avoid infinite nests.
  3. Preserve order: Process left-to-right.
Step 1: Start with [1, [2,3], [4, [5,6], 7], 8]
Step 2: Extract 1 → result: [1]
Step 3: Dive into [2,3] → extract 2,3 → result: [1,2,3]
Step 4: Dive into [4, [5,6], 7] → extract 4, dive deeper to 5,6 → extract 7 → result: [1,2,3,4,5,6,7]
Step 5: Extract 8 → result: [1,2,3,4,5,6,7,8]
Enter fullscreen mode Exit fullscreen mode

Flattening step-by-step


Different Approaches to Flatten Arrays

Native flat(depth) (ES2019+)

Simplest: Going to flat the given array upto the specified depth. depth means upto which level it's going to be spread. arr.flat(Infinity) handles any depth.

[1, [2, [3]]].flat(Infinity); // [1,2,3]
[1, [2, [3]]].flat(1); // [1,2,[3]]
Enter fullscreen mode Exit fullscreen mode

Pros: Built-in, readable. Cons: Browser support (IE doesn't support).

Iterative with reduce + concat

No recursion—great for huge arrays.

function flatten(arr) {
  return arr.reduce((acc, val) => Array.isArray(val) ? acc.concat(...val) : acc.concat(val), []);
}
Enter fullscreen mode Exit fullscreen mode

Step-by-step: Accumulator starts empty, concat spreads nested arrays and adds them after spreading, otherwise simple add.

Recursive Custom (Polyfill Style)

Dive deep with a helper function—scales to any depth. We going to discuss about this in the next section.


Common Interview Scenarios

Interviewers love asking: "Implement Array.prototype.flat polyfill!" or "Flatten without natives, handle depth."

Building your own Polyfill: A Strong Solution

Here's your code—clean and correct:

Array.prototype.myFlat = function(depth = 1) {
    const result = [];
    const flatten = function(arr, depth) {
        for(let i = 0; i < arr.length; i++) {
            if (!arr.hasOwnProperty(i)) 
                continue;
            if(Array.isArray(arr[i]) && depth > 0) {
                flatten(arr[i], depth - 1);
            } else {
                result.push(arr[i]);
            }
        }
    }
    flatten(this, depth);
    return result;
}

console.log([1,2,3,4,5,[6,7,8,[9,10]]].myFlat(Infinity)); // [1,2,3,4,5,6,7,8,9,10]
console.log([1,,3].myFlat(1)); // [1,3]
Enter fullscreen mode Exit fullscreen mode

Understanding polyfill code

Analysis (Problem-Solving Thinking):

  • In this polyfill, an empty array been taken called as result.
  • It uses a helper function, that iterate over every element of the array.
  • If it's an simple value then directly push to the result array.
  • If the element is an array and the depth is greater than 0, then it will call the same helper fucntion using the element which is actually an array with depth-1
  • after the all the nested array been spread (if depth=Infinity) or if the depth becomes 0, then it will stop and return the result array.

Note: I would recommend a dry run by your own. take a pen-paper and try dry-run

Interview Tip: Explain trade-offs: Recursion shines for trees; iteration for 1M+ elements. Here time-complexity: O(n) time (visits each element once) and O(depth) stack space.


Flattening isn't just a trick—it's a mindset for taming messy data. Practice these, tweak your polyfill and you'll crush interviews. Next time you hit nested chaos, myFlat(Infinity) has your back.

Top comments (2)

Collapse
 
jonrandy profile image
Jon Randy 🎖️

Your polyfill is not correct. It doesn't handle sparse arrays correctly. Try it with this array:

[1,,2]
Enter fullscreen mode Exit fullscreen mode

You'll get a different result to the native one.

Collapse
 
ritam369 profile image
Ritam Saha

Ohh yes you are right, I forgot to handle that edge case, thank you for your suggestion😃
I have changed the code now, previously for the gaps it was taking the element as undefined, now it checks whether the value comes within the array (attached a checking with .hasOwnProperty()) otherwise, it will skip the holes.