How Lodash _.assign Overwrites Object Properties
In the Lodash JavaScript library, _.assign merges the
own enumerable string keyed properties of one or more source objects
directly into a destination target object. When resolving key
collisions, _.assign strictly overwrites existing
properties on the target using a left-to-right evaluation order, meaning
the last source object containing a conflicting key wins. This article
explains the exact mechanics of how _.assign handles
property overwriting, its shallow copying behavior, and how it differs
from deep merging.
The Basic Overwrite Mechanism
The syntax for the function is:
_.assign(object, [sources])The first argument is the target object, and every subsequent
argument is a source object. When _.assign is called, it
iterates over each source object from left to right. For every own
enumerable property found in a source:
- It checks the key name.
- It assigns the value of that key directly to the target object.
- If the target object (or a previous source object) already has a property with the same key, the existing value is immediately replaced with the new value.
Left-to-Right Evaluation
Because properties are assigned in the order the sources appear, subsequent arguments take precedence over prior ones.
const target = { a: 1, b: 2 };
const source1 = { b: 3, c: 4 };
const source2 = { b: 5, d: 6 };
_.assign(target, source1, source2);
console.log(target);
// Output: { a: 1, b: 5, c: 4, d: 6 }In this example:
source1overwritestarget.b(changing it from2to3).source2then overwritesbagain (changing it from3to5).
Shallow Assignment vs. Recursive Merging
The overwriting process in _.assign is strictly
shallow. It uses standard JavaScript assignment
semantics under the hood (similar to Object.assign()).
If a property on both the target and the source is an object,
_.assign does not inspect or merge the nested properties
inside. Instead, it replaces the entire object reference with the one
provided by the source.
const target = {
user: {
name: 'Alice',
role: 'Admin'
}
};
const source = {
user: {
name: 'Bob'
}
};
_.assign(target, source);
console.log(target);
// Output: { user: { name: 'Bob' } }
// Notice that 'role: Admin' was completely erased, not preserved.If you need nested objects to merge rather than be completely
replaced, use Lodash's _.merge instead of
_.assign.
Handling of Undefined and Null Values
_.assign treats undefined as a valid value
to overwrite existing data. If a source object explicitly defines a key
as undefined, it will overwrite the target's existing value
with undefined.
const target = { status: 'active' };
const source = { status: undefined };
_.assign(target, source);
console.log(target);
// Output: { status: undefined }If you want to skip overwriting values when the source value is
undefined, Lodash provides _.assignWith or
_.defaults, which only assign values if the destination
property resolves to undefined.
Target Mutation
A critical aspect of how _.assign works is that it
mutates the target object in place and returns that same reference. If
you want to create a new object without altering the original target,
pass an empty object literal as the first argument:
const original = { a: 1 };
const update = { a: 2 };
const result = _.assign({}, original, update);
console.log(original.a); // 1 (unchanged)
console.log(result.a); // 2