It is highly common to need to merge two objects in JavaScript, it is something that you may find yourself needing to do on a daily basis in pretty much any JavaScript position.
This post is going to go over everything you need to know to be able to merge two objects in JavaScript for both shallow and deep objects, objects with the same key, preventing data loss from overwriting and more.
Let’s get started.
How to merge two objects in JavaScript
The easiest way to merge two objects in JavaScript is with the ES6 spread syntax / operator (...
).
All you have to do is insert one object into another object along with the spread syntax and any object you use the spread syntax on will be merged into the parent object.
Here is an example of how you can use the spread syntax to merge two objects in JavaScript:
const objOne = { a: "a" }
const objTwo = { ...objOne, b: "b" }
console.log(objTwo) // { a: "a", b: "b" }
As you can see in the above example we have pulled the properties from the first object into the second by merging the two objects with the use of the spread syntax.
It is worth noting that this will only merge to a shallow level and that if both objects share a property the second in order will overwrite the first.
What that means is it will still transfer all properties, but if you have a nested object then that object will remain nested and the properties will not be merged into the parent object.
Here is an example of this will look:
const objOne = { a: "a", x: { y: "y" } }
const objTwo = { ...objOne, b: "b" }
console.log(objTwo) // { a: "a", b: "b", x: { y: "y" } }
As you can see the nested object is still nested, so how can we merge it as well?
How to deep merge two objects in JavaScript
To deep merge two objects in JavaScript is a little harder to do than shallow merging which is why it is always important to normalize and try to keep your data as flat as possible to avoid needing to deep merge.
With that said, sometimes you can’t avoid having to deep merge two objects, so let’s take a look at how you can.
The first way is actually pretty simple, for most cases you will know the structure of your data, and because of that we can deep merge it manually to avoid any recursive functions having to do it for us.
To deep merge manually it is actually pretty similar to the shallow merge except we need to make sure we merge any nested objects as well using the spread syntax.
Here is an example of how a manual deep merge could look:
const objOne = { a: "a", x: { y: "y" } }
const objTwo = { ...objOne, b: "b", ...objOne.x }
delete objTwo.x
console.log(objTwo) // { a: "a", b: "b", y: "y" }
If you want to avoid removing the nested object after it has been merged then you can instead selectively choose the data you want like so:
const objOne = { a: "a", x: { y: "y" } }
const objTwo = { a: objOne.a, b: "b", ...objOne.x }
console.log(objTwo) // { a: "a", b: "b", y: "y" }
If you do not know the data within the object or you need a more generic approach, your best bet is to use a helper method like merge from lodash which will perform a deep merge for you.
However, if you don’t want to import a library just for deep merging or if you don’t want to use lodash then you will need to create a recursive function to be able to deep merge two objects.
Here is an example of a generic helper method that uses recursion to deep merge and flatten two objects in JavaScript:
function deepMergeFlatten(obj1, obj2) {
const keys = Object.keys(obj2)
let nextObj = { ...obj1 }
for (let i = 0; i < keys.length; i += 1) {
const key = keys[i]
const value = obj2[key]
if (typeof value === "object" && value !== null) {
nextObj = { ...nextObj, ...deepMergeFlatten(nextObj, value) }
} else {
nextObj = { ...nextObj, [key]: value }
}
}
return nextObj
}
deepMergeFlatten(
{ a: "a" },
{ b: "b", c: { c: "c", d: { d: "d", e: { e: "e" } } } }
) // { a: "a", b: "b", c: "c", d: "d", e: "e" }
In the example above the helper method will loop over each key in an object whilst checking if the value for the key is an object or not, if the value is an object then it will call itself with the object to start the process over again with the smaller nested object, otherwise if it is not an object then it will add it into the new object.
With this recursive function, after all the objects have been found and merged together it will return a single object with all values merged together.
How to merge two objects with same key in JavaScript
When you merge two objects with the same key in JavaScript you need to decide which one will take precedence in the merged array. The one you want to key with the same key must be last in the merging of the two objects with the same key.
Here is an example of how to merge two objects with the same key in JavaScript:
const objA = { a: 10 }
const objB = { a: 15 }
console.log({ ...objA, ...objB }) // { a: 15 }
console.log({ ...objB, ...objA }) // { a: 10 }
As you can see from this example you just need to make sure that you merge the two objects in the correct order to preserve the value of the key you need.
Whichever property comes last will overwrite any property with the same key before it.
How to merge two objects without overwriting in JavaScript
To merge two objects without overwriting in JavaScript is a little similar to the manual deep merge.
If you have a nested object but you don’t want to overwrite the property you just need to spread the two properties into a new version of the property.
Here is an example how you can do this:
const obj1 = { a: { num: 123 }, x: "x" }
const obj2 = { a: { letters: "abc" }, z: "z" }
console.log({
...obj1,
...obj2,
a: {
...obj1.a,
...obj2.a,
},
}) // { a: { num: 123, letters: "abc" }, x: "x", z: "z" }
As you can see from this example we create a new property with precedence after merging the original two objects in, and then we use the spread syntax once again within the new version of the property for both objects with that property to extract all the keys without overwriting and losing the information.
Summary
There we have how to merge two objects in JavaScript, if you want more like this be sure to check out some of my other posts!