Skip to content
⚠️ This article was written in 2018. Some content may be outdated.

Several Ways to Flatten JavaScript Arrays

Turning a multi-level nested array into a flat one is a common requirement. Here are several implementation approaches with a comparison of when to use each.

The Scenario

javascript
const nested = [1, [2, 3], [4, [5, 6]], [7, [8, [9]]]];
// Goal: [1, 2, 3, 4, 5, 6, 7, 8, 9]

Method 1: Recursion

javascript
function flatten(arr) {
  return arr.reduce((flat, item) => {
    return flat.concat(Array.isArray(item) ? flatten(item) : item);
  }, []);
}

flatten([1, [2, [3, [4]]]]); // [1, 2, 3, 4]

Method 2: Spread Operator Loop

javascript
function flatten(arr) {
  while (arr.some((item) => Array.isArray(item))) {
    arr = [].concat(...arr);
  }
  return arr;
}

Each iteration peels off one level of nesting until the array is flat.

Method 3: toString (integers only)

javascript
[1, [2, [3, [4]]]].toString().split(",").map(Number);
// [1, 2, 3, 4]

Only works for arrays of pure integers — limited use cases.

Method 4: Array.flat (ES2019)

javascript
// Flatten one level
[1, [2, [3]]]
  .flat() // [1, 2, [3]]

  [
    // Flatten two levels
    (1, [2, [3, [4]]])
  ].flat(2) // [1, 2, 3, [4]]

  [
    // Flatten all levels
    (1, [2, [3, [4]]])
  ].flat(Infinity); // [1, 2, 3, 4]

Cleanest option. Supported in Chrome 69+ (late 2018) — needs a polyfill for older environments.

Flatten to a Specified Depth

javascript
function flattenDepth(arr, depth = 1) {
  if (depth === 0) return arr.slice();
  return arr.reduce((flat, item) => {
    if (Array.isArray(item) && depth > 0) {
      return flat.concat(flattenDepth(item, depth - 1));
    }
    return flat.concat(item);
  }, []);
}

flattenDepth([1, [2, [3, [4]]]], 2); // [1, 2, 3, [4]]

Real-World Example

javascript
// Scenario: tree-structured menu data — get all nodes
const menuTree = [
  { id: 1, name: "Home" },
  {
    id: 2,
    name: "User Management",
    children: [
      { id: 3, name: "User List" },
      { id: 4, name: "Role Management" },
    ],
  },
];

// Get all menu items (including parent nodes)
function flattenMenu(menus) {
  return menus.reduce((flat, menu) => {
    if (menu.children) {
      return flat.concat(menu, flattenMenu(menu.children));
    }
    return flat.concat(menu);
  }, []);
}

flattenMenu(menuTree);
// [{ id: 1 }, { id: 2 }, { id: 3 }, { id: 4 }]

Performance

For large arrays, the recursive approach is fastest. Array.flat is also optimised internally. The toString approach is expensive due to string creation.

Summary

  • Daily development: flat(Infinity) is cleanest (confirm browser support)
  • Needs to support older browsers: use the recursive reduce approach
  • Integer-only arrays: toString().split(',').map(Number) works too
  • Tree data to flat list: use recursion to handle children

MIT Licensed