Javascript Merge And Assign
With the new es2015 Object.assign functionality you can easily merge
objects
together. However there is also a merge
function available in different popular
libraries.
The difference between merge and assign was source of confusion for me and I suspect It might be for others. Hopefully this article will clarify things.
All code is editable with live results.
Object.Assign
Let’s start with what we have available in the language: Object.assign
.
It is shallow. It means it won’t merge recursively Object properties.
It only copies from the top level.
So in the following example, the foo
prop from Obj1
replaces the one from Obj2
.
Additionally, It copies only direct properties and not ones accessible through the prototype link.
It copies Symbol properties;
However you may think those symbol properties are not copied since they are not enumerable
It does not copy non-enumerable properties other than symbols
If your property was not writable it becomes writable!
If your property was a function, assign
copies the function but be aware it may not be visible in some consoles (not showing on my current version of Google Chrome for example) .
lodash Assign
_.assign
is like Object.assign
but will work in non-es6 environments.
lodash Merge
This is where it gets really interesting. _.merge
will recursively copy object
properties.
Since the copy was recursive, foo
was not replaced but instead
the foo
array first element replaces the one from Obj2 foo
.
It can be good or bad. Maybe you wanted to add 4 to the end of the array? Of course I could replace it with an Object instead and that will work
If we forgot the extra typing,that solves our particular problem but maybe that’s not what you wanted to do. Maybe replacing the first element of the array was what you wanted. In general you should be careful when you merge deep objects. This is not something trivial to do.
ImmutableJS
Immutable merge
returns a new object but is shallow like Object.Assign!
I find this a big source of confusion since Immutable uses merge to assign…
Immutable mergeDeep
is ImmutableJS equivalent to _.merge
except that it does
not mutate the object of course.
Review
assign
can catch you off guard as some of its behaviour might seem unexpected.
assign
will copy properties at the top level, won’t copy non-enumerable properties,
won’t copy prototype properties, all copied properties become writable.
assign
copies even thought they are not enumerable with many default js functions.
merge
and assign
have different behaviours
regarding deep properties. merge
recursively merges deep
properties. It might
seem to be what most programmers would expect by default.
However be aware of what you are trying to do,
especially merging responses from an API. merge
can be the right tool for the job in some occasions, assign
in others.