Both Object.assign and Object spread only do a shallow merge.
An example of the problem:
// No object nesting
const x = { a: 1 }
const y = { b: 1 }
const z = { ...x, ...y } // { a: 1, b: 1 }
The output is what you'd expect. However if I try this:
// Object nesting
const x = { a: { a: 1 } }
const y = { a: { b: 1 } }
const z = { ...x, ...y } // { a: { b: 1 } }
Instead of
{ a: { a: 1, b: 1 } }
you get
{ a: { b: 1 } }
x is completely overwritten because the spread syntax only goes one level deep. This is the same with Object.assign()
.
Is there a way to do this?
Since this issue is still active, here's another approach:
If npm libraries can be used as a solution, object-merge-advanced from yours truly allows to merge objects deeply and customise/override every single merge action using a familiar callback function. The main idea of it is more than just deep merging — what happens with the value when two keys are the same? This library takes care of that — when two keys clash,
object-merge-advanced
weighs the types, aiming to retain as much data as possible after merging:First input argument's key is marked #1, second argument's — #2. Depending on each type, one is chosen for the result key's value. In diagram, "an object" means a plain object (not array etc).
When keys don't clash, they all enter the result.
From your example snippet, if you used
object-merge-advanced
to merge your code snippet:It's algorithm recursively traverses all input object keys, compares and builds and returns the new merged result.
The following function makes a deep copy of objects, it covers copying primitive, arrays as well as object
A simple solution with ES5 (overwrite existing value):
I tried to write an
Object.assignDeep
which is based on the pollyfill ofObject.assign
on mdn.(ES5)