How to merge two objects in JavaScript
By Flavio Copes
Learn how to merge two JavaScript objects into a new one with the spread operator, where later properties win, or do a deep merge with the Lodash merge().
To merge two objects in JavaScript, use the spread operator. It copies the properties of both objects into a new one.
ES6 in 2015 introduced the spread operator, which is the perfect way to merge two simple objects into one:
const object1 = {
name: 'Flavio'
}
const object2 = {
age: 35
}
const object3 = { ...object1, ...object2 }
// { name: 'Flavio', age: 35 }
The spread operator copies all the enumerable own properties of each object into object3. The two original objects are not modified.
What happens with duplicate properties?
If both objects have a property with the same name, the second object property overwrites the first:
const person = { name: 'Flavio', age: 35 }
const update = { age: 36 }
const updated = { ...person, ...update }
// { name: 'Flavio', age: 36 }
Order matters. Whatever you spread last wins. This is handy when you have a set of defaults and you want to override some of them.
Alternatively, you can use Object.assign():
const object3 = Object.assign({}, object1, object2)
The result is the same. Be careful with the first argument, though. Object.assign() copies the properties into it, so passing {} gives you a new object. If you pass object1 instead, you mutate it.
The pitfall: nested objects
The spread operator performs a shallow merge. It only copies the top-level properties. If a property holds an object, that object is replaced entirely, not merged:
const person = {
name: 'Flavio',
address: {
city: 'Milan',
zip: '20100'
}
}
const update = {
address: {
city: 'Rome'
}
}
const merged = { ...person, ...update }
// { name: 'Flavio', address: { city: 'Rome' } }
Notice that zip is gone. The whole address object from update took the place of the original one, instead of just changing the city.
This bites hard with configuration objects, where you merge user options over defaults and a whole section of the defaults silently disappears.
The best solution in this case is to use Lodash and its merge() method, which will perform a deeper merge, recursively merging object properties and arrays:
import merge from 'lodash.merge'
const merged = merge({}, person, update)
// { name: 'Flavio', address: { city: 'Rome', zip: '20100' } }
Here city was updated and zip was preserved, because the nested objects were merged property by property.
See the documentation for it on the Lodash docs.
Related posts about js: