Flattening a nested array
Flattening an array means turning a nested structure into a single flat list of values. Modern JavaScript has the flat() method for exactly this, and it takes a depth argument; the other approaches (recursion, flatMap(), toString()) still have their niches.
Theory
TL;DR
arr.flat()unwraps one level of nesting.arr.flat(2)unwraps two levels,arr.flat(Infinity)unwraps everything.- None of these approaches mutates the source array; they all return a new one.
- Before ES2019 people wrote a recursive
flattenon top ofreduce()plusArray.isArray(). flatMap()ismap()plus one level of flattening in a single pass.toString().split(',')only works for numbers and strings, and it returns strings.
Quick example
Take this array:
const arr = [1, [2, 3], [4, [5, 6]]];We want [1, 2, 3, 4, 5, 6]:
console.log(arr.flat(Infinity)); // [1, 2, 3, 4, 5, 6]flat() and the flattening depth
The simplest way is flat() (ES2019 and later):
const flattened = arr.flat();
console.log(flattened); // [1, 2, 3, 4, [5, 6]]By default flat() unwraps only one level of nesting. The depth is set by the argument:
const deeplyFlattened = arr.flat(2);
console.log(deeplyFlattened); // [1, 2, 3, 4, 5, 6]flat(1)is one level,flat(2)is two levels,flat(Infinity)is full flattening, whatever the depth.
An example with deep nesting:
const nested = [1, [2, [3, [4]]]];
console.log(nested.flat(Infinity)); // [1, 2, 3, 4]This is the handiest and most modern way to flatten an array. As a bonus, flat() also drops the holes of a sparse array: [1, , 3].flat() gives [1, 3].
Recursion, the way it was done before flat()
function flatten(arr) {
return arr.reduce(
(acc, val) => acc.concat(Array.isArray(val) ? flatten(val) : val),
[]
);
}
console.log(flatten([1, [2, [3, 4]], 5]));
// [1, 2, 3, 4, 5]- check every element: if it is an array, call
flattenrecursively; - if it is not, push the value into the result.
This version is still useful when you need custom logic, for example skipping null or flattening only certain branches.
toString() for numbers and strings
[1, [2, [3, 4]]].toString().split(',');
// ["1", "2", "3", "4"]This works only when the array holds no objects and no null, because everything is converted to strings. Numbers come back as strings too, so it is more of a trick than a real approach.
flatMap() for transforming while flattening
const arr = [1, 2, [3, 4]];
const result = arr.flatMap(x => (Array.isArray(x) ? x : [x]));
console.log(result); // [1, 2, 3, 4]flatMap() transforms elements and flattens one level at the same time, so it saves a pass compared with map().flat().
Comparing the options
| Way | Works with | Depth | Mutates | Modern |
|---|---|---|---|---|
arr.flat() | array | 1 by default | No | Yes, ES2019 and later |
arr.flat(Infinity) | multi-dimensional | all levels | No | Yes |
| Recursion | array | any | No | Yes, universal |
flatMap() | array | 1 level | No | Yes |
toString().split() | numbers, strings | all levels | No | Limited |
Bottom line: to flatten an array,
javascriptconst flat = arr.flat(Infinity);is short, safe and clear.
Common mistakes
- Expecting
flat()to unwrap everything. With no argument it removes exactly one level; deep structures needflat(Infinity). - Assuming
flat()mutates the array. It returns a new array, so the result has to be assigned:arr = arr.flat(). - Running
toString().split(',')on objects. Objects turn into[object Object], whilenullandundefinedbecome empty strings. - Losing types after
split(). Numbers come back as strings, so an extra.map(Number)is required. - Recursion without a type check as the base case. Without
Array.isArray(val)a string would also go into the recursion, since it is iterable. - Using
flatMap()for deep flattening. It removes only one level, so[[1, [2]]]stays nested in the result.
Short Answer
Interview readyA concise answer to help you respond confidently on this topic during an interview.