Lodash Union vs Flatten: Merging Nested Arrays

In the Lodash JavaScript library, _.union combines multiple arrays into a single array of unique elements, but it only unpacks the top-level arguments passed to it, leaving nested array structures intact. In contrast, strict flattening methods like _.flatten and _.flattenDeep actively dismantle inner array structures to reduce their dimensional depth. Understanding how _.union preserves nested structures and performs reference-based equality checks is essential when working with multidimensional datasets.

Shallow Argument Unpacking vs. Recursive Flattening

When you pass multiple arrays to _.union(...arrays), Lodash performs an initial shallow concatenation across the provided arguments. It creates a single working list containing all the top-level elements of each input array. However, _.union does not inspect or flatten any arrays nested inside those elements.

const array1 = [1, [2]];
const array2 = [3, [4]];

_.union(array1, array2);
// Output: [1, [2], 3, [4]]

Strict flattening methods behave differently by targeting the elements inside the arrays:

const nested = [1, [2, [3]]];

_.flatten(nested);     // Output: [1, 2, [3]]
_.flattenDeep(nested); // Output: [1, 2, 3]

Reference Equality in Nested Deduplication

The core purpose of _.union is to return an array of unique values using the SameValueZero equality algorithm. For primitive values like numbers and strings, duplicates are detected and removed by value. For nested arrays and objects, SameValueZero compares by memory reference rather than structural content.

If two input arrays contain nested arrays that look identical but occupy different locations in memory, _.union treats them as distinct values:

const a = [1, [2]];
const b = [3, [2]];

_.union(a, b);
// Output: [1, [2], 3, [2]]

Because [2] in a and [2] in b are separate object references, both remain in the final array. Deduplication of nested arrays only occurs if both inputs reference the exact same array instance:

const sharedRef = [2];
const a = [1, sharedRef];
const b = [3, sharedRef];

_.union(a, b);
// Output: [1, [2], 3]

Comparing Use Cases

Choosing between _.union and strict flattening depends on whether your data architecture requires reference retention or value extraction: