Lodash assign Overwrite Priority for Complex Keys
This article examines how Lodash’s _.assign method
resolves key collisions when combining JavaScript objects with
overlapping and complex properties. You will learn the strict
left-to-right evaluation order used by the method, how shallow
assignment fundamentally impacts nested objects and arrays, and how
_.assign differs from recursive merging alternatives like
_.merge.
The Left-to-Right Precedence Rule
Lodash’s _.assign function applies own enumerable
string-keyed properties from one or more source objects onto a target
object. The syntax is structured as:
_.assign(destination, [sources])When resolving key collisions, _.assign adheres strictly
to a left-to-right evaluation order. The destination object serves as
the baseline, and each subsequent source object provided in the argument
list processes sequentially:
- Properties from
source1overwrite properties with identical names in thedestinationobject. - Properties from
source2overwrite properties from bothdestinationandsource1. - This sequence continues until the final source argument has been processed.
The destination object is directly mutated in-place and returned as the final result.
Shallow Assignment and Complex Overlapping Keys
The most critical architectural detail of _.assign
regarding complex data structures (such as nested objects and arrays) is
that it performs shallow copying, not deep recursive
merging.
When an overlapping key contains a complex object,
_.assign does not inspect or reconcile the inner properties
of that object. Instead, the reference from the right-most source
completely replaces whatever existed at that key previously.
Example: Nested Object Replacement
const destination = {
config: {
debug: true,
timeout: 1000
}
};
const source = {
config: {
timeout: 5000,
retries: 3
}
};
_.assign(destination, source);Resulting destination:
{
config: {
timeout: 5000,
retries: 3
}
}In this case, destination.config.debug is not preserved.
Because _.assign is strictly a shallow operation, the
entire config object reference in source
completely overwrites the config object in
destination.
Overwrite Behavior
with undefined Values
Unlike _.defaults or _.mergeWith (when
customized), _.assign treats explicit
undefined values as valid assignments:
const destination = { environment: 'production' };
const source = { environment: undefined };
_.assign(destination, source);
// destination.environment is now undefinedIf an overlapping key exists on a later source object and its value
is explicitly set to undefined, it will successfully
overwrite the defined value present in earlier objects.
_.assign vs.
_.merge for Complex Keys
To achieve deep recursive property preservation rather than wholesale overwriting:
- Use
_.assign: When later objects must completely dictate the entire state of any shared top-level keys, discarding previous nested structures entirely. - Use
_.merge: When overlapping nested keys should combine recursively, retaining untouched child properties from earlier sources.