JavaScript Array.flatMap() - Map and Flatten in One Step
Deep dive into Array.flatMap() for one-to-many transformations, combined filter+map, and efficient flattening. Includes performance comparisons with map().flat(). Free reference.
Detailed Explanation
Understanding flatMap()
Array.flatMap() combines two operations — map() and flat(1) — into a single, more efficient pass. The callback can return a single value, an array (which gets flattened one level), or an empty array (which filters out the element).
Basic Syntax
const result = array.flatMap((element, index, array) => {
return newElement; // or [a, b] or []
});
Splitting and Flattening
The most common use case — splitting strings across an array:
const lines = ["hello world", "foo bar baz", "one"];
const words = lines.flatMap(line => line.split(" "));
// words: ["hello", "world", "foo", "bar", "baz", "one"]
Without flatMap: lines.map(l => l.split(" ")).flat() — two passes instead of one.
Filter + Map Combined
Return [] to exclude, [transformed] to include:
const nums = [1, 2, 3, 4, 5, 6, 7, 8];
// Keep even numbers, square them
const result = nums.flatMap(n =>
n % 2 === 0 ? [n ** 2] : []
);
// result: [4, 16, 36, 64]
This is equivalent to .filter(n => n % 2 === 0).map(n => n ** 2) but in a single pass.
One-to-Many Expansion
Each element can expand into multiple output elements:
const users = [
{ name: "Alice", roles: ["admin", "user"] },
{ name: "Bob", roles: ["user"] }
];
const assignments = users.flatMap(u =>
u.roles.map(role => ({ name: u.name, role }))
);
// assignments: [
// {name:"Alice", role:"admin"},
// {name:"Alice", role:"user"},
// {name:"Bob", role:"user"}
// ]
Inserting Between Elements
const items = ["a", "b", "c"];
const withSeparators = items.flatMap((item, i) =>
i < items.length - 1 ? [item, "|"] : [item]
);
// withSeparators: ["a", "|", "b", "|", "c"]
Performance
flatMap is ~1.5-2x faster than separate map().flat() calls because:
- No intermediate array allocation
- Single iteration instead of two
- Engine optimizations for the combined operation
Only flattens one level deep. For deeper flattening, use map().flat(depth).
Use Case
Use flatMap() when each input element should produce zero, one, or multiple output elements. Perfect for expanding nested data (user.roles, node.children), splitting strings into tokens, and any pattern where filter+map can be combined into a single pass for better performance.