Developers often need to merge or copy objects for tasks like combining data or creating new instances. Techniques like the spread ( ...
) operator (used for merging properties of multiple objects) and the Object.assign()
method (for copying properties from one object to another) are essential tools for these tasks. However, understanding when and how to use them is crucial for effective object manipulation. In this article, I’ll cover some practical applications of these methods, their strengths and weaknesses, and the concept of deep copying before merging nested objects.
Table of contents
Approaches for Merging Objects
1. The Spread Operator ( ...
)
The spread operator (...
) is a common approach to merge objects in JavaScript. It has the form {...object1, ...object2}
. When properties with the same keys exist in the source objects, the spread operator overwrites the values in the target object with the latest source object’s values.
const defaults = { color: 'red', size: 'medium' };
const userSettings = { color: 'blue' };
const combinedSettings = { ...defaults, ...userSettings };
console.log(combinedSettings);
// Output: { color: 'blue', size: 'medium' }
2. The Object.assign()
Method
Object.assign()
is a JavaScript method for merging objects. Its syntax is Object.assign(target, source1, source2, ...)
, where you merge source objects into the target
object. When properties with the same keys exist in the source objects, Object.assign()
overwrites the values in the target object with the latest source object’s values.
const defaults = { color: 'red', size: 'medium' };
const userSettings = { color: 'blue' };
const combinedSettings = Object.assign({}, defaults, userSettings);
console.log(combinedSettings);
// Output: { color: 'blue', size: 'medium' }
Pitfalls and Considerations
Here are the potential pitfalls and issues with both the spread operator and Object.assign()
method for merging objects in JavaScript:
1. Shallow copying
Both the spread operator and Object.assign()
perform shallow copying when merging objects. This means that nested objects are still references to the original objects. Modifying the nested objects in the merged object can affect the original objects, which may lead to unintended side effects.
See Deep Merging below.
2. Overwriting properties
When merging objects with properties that have the same keys, both the spread operator and Object.assign()
overwrite the values in the resulting object with values from the latest source object. This behavior may cause the loss of data if not handled carefully.
3. Compatibility issues
The spread operator is part of ECMAScript 2015 (ES6) and is not supported in older JavaScript environments or browsers, such as Internet Explorer. This may cause compatibility issues if your code needs to run in older environments. In such cases, it’s better to use Object.assign()
, which has wider support.
4. Non-enumerable properties
Both the spread operator and Object.assign()
only copy enumerable properties from source objects to the target object. Non-enumerable properties are not copied during the merging process, which may lead to missing data or unexpected behavior.
5. Performance concerns
In cases where you need to merge large objects or perform merging operations frequently, using Object.assign()
or the spread operator may cause performance issues due to the creation of new objects during the merging process.
6. Prototype properties
Object.assign()
copies properties from the source object’s prototype to the target object, which may lead to unexpected behavior if the source object’s prototype has properties that conflict with the target object’s properties. The spread operator, on the other hand, does not copy prototype properties.
It’s essential to be aware of these pitfalls and issues when using the spread operator or Object.assign()
to merge objects in JavaScript. In specific scenarios, you may need to employ alternative approaches, such as deep cloning or deep merging functions, to overcome these limitations.
Which One to Use
Both Object.assign()
and the spread operator effectively merge objects. The spread operator is more concise and modern, while Object.assign()
offers better compatibility with older JavaScript environments.
To decide which method to use, consider:
- If your environment supports the spread operator (such as the latest ECMAScript version), use it for its concise syntax.
- If compatibility with older JavaScript environments is essential, choose
Object.assign()
. - If you need to copy a nested object (one with objects nested inside it) read on to Deep Copying Objects.
Deep Merging: Deep Copy & Merge Objects
Both the spread operator and Object.assign() create a shallow copy of the object(s) being copied. Essentially this means the new object will have references to the same nested objects (e.g. arrays and functions) as the original object, rather than having copies of them.
Knowing and avoiding this is essential before merging objects together.
The example below shows how editing nested objects on a copied object can affect the original:
const planet = {
name: 'Earth',
emoji: '🌍',
info: {
type: 'terrestrial',
moons: 1
}
};
// Shallow copy using the spread operator
const shallowCopyPlanet = { ...planet };
// Modifying the nested object in the shallow copy
shallowCopyPlanet.info.moons = 2;
console.log('Original planet:', planet.info.moons);
// Original planet: 2
console.log('Shallow copy of the planet:', shallowCopyPlanet.info.moons);
// Shallow copy of the planet: 2
The output of this code shows that the info.moons property on the original object planet
has been changed by editing it in shallowCopyPlanet
(You probably don’t want this).
A custom Deep Merging function
Here’s a function that deep copies multiple objects before merging them and returns a single object. In the code, the deepMergeObjects
function takes any number of input objects, creates deep copies of them using the JSON.parse(JSON.stringify())
technique, and then merges them using the spread operator inside the reduce()
method. The merged object will contain deep copies of the properties from the input objects.
const deepMergeObjects = (...objects) => {
const deepCopyObjects = objects.map(object => JSON.parse(JSON.stringify(object)));
return deepCopyObjects.reduce((merged, current) => ({ ...merged, ...current }), {});
}
// Example usage:
const countries = {
USA: {
capital: 'Washington D.C.',
emoji: '🇺🇸',
population: 331000000
}
};
const countriesDetails = {
USA: {
language: 'English',
currency: 'USD'
},
Germany: {
capital: 'Berlin',
emoji: '🇩🇪',
language: 'German',
currency: 'EUR',
population: 83000000
}
};
const mergedData = deepMergeObjects(countries, countriesDetails);
Conclusion
Thanks for reading! I hope this article has given you a deep understanding of merging objects in JavaScript and not just a shallow introduction. Being able to combine objects in this should merge nicely with your JavaScript skills and spread your coding prowess. For any questions or comments, join us over at the SitePoint Community Forum.
FAQs on Merging Objects in JavaScript
What is the concept of merging objects in JavaScript?
Merging objects in JavaScript refers to the process of combining two or more objects into a single object. This is often done to consolidate properties and methods from multiple objects into one, making it easier to manage and manipulate data. The merged object will contain all the properties and methods from the original objects. If there are duplicate properties, the value from the last object will overwrite the previous ones.
How can I merge objects in JavaScript using the Spread operator?
The Spread operator (…) in JavaScript is a modern and efficient way to merge objects. It allows an iterable such as an array expression or string to be expanded in places where zero or more arguments or elements are expected. Here’s an example of how you can use it:
const obj1 = { a: 1, b: 2 };
const obj2 = { b: 3, c: 4 };
const mergedObj = { ...obj1, ...obj2 };
console.log(mergedObj); // Output: { a: 1, b: 3, c: 4 }
What is the role of Object.assign() method in merging objects?
The Object.assign() method is used to copy the values of all enumerable own properties from one or more source objects to a target object. It will return the target object. It’s a very useful method for merging objects as it allows you to combine multiple source objects into a single target object. However, it’s important to note that if the same property is found in more than one object, the value from the last object with that property will overwrite the previous ones.
Can I merge nested objects in JavaScript?
Yes, you can merge nested objects in JavaScript. However, the process is a bit more complex because you need to ensure that the nested objects are also merged correctly, not just the top-level properties. This is often referred to as a deep merge. Neither Object.assign() nor the spread operator perform a deep merge by default. You would need to implement a custom function or use a library like Lodash for this purpose.
What happens to duplicate properties when merging objects?
When merging objects in JavaScript, if there are duplicate properties, the value from the last object will overwrite the previous ones. This is because when an object is merged, it iterates over the properties of the source objects and assigns them to the target object. If a property already exists on the target object, its value is replaced with the new value.
Is it possible to merge arrays like objects in JavaScript?
Yes, arrays can be merged in JavaScript using similar methods to objects. The spread operator is a common way to merge arrays. Here’s an example:
const arr1 = [1, 2, 3];
const arr2 = [4, 5, 6];
const mergedArr = [...arr1, ...arr2];
console.log(mergedArr); // Output: [1, 2, 3, 4, 5, 6]
How can I merge objects without mutating the original objects?
Both the spread operator and Object.assign() method create a new object when merging, leaving the original objects unmutated. This is a key feature of these methods as it promotes immutability, a core concept in functional programming where data is never changed.
Can I merge objects with different data types in JavaScript?
Yes, you can merge objects with different data types in JavaScript. The merged object will contain all the properties and methods from the original objects, regardless of their data types. However, if there are duplicate properties with different data types, the value from the last object will overwrite the previous ones.
What is the performance impact of merging objects in JavaScript?
Merging objects in JavaScript can have a performance impact, especially when dealing with large objects. Both the spread operator and Object.assign() method have a time complexity of O(n), where n is the total number of properties in the source objects. Therefore, it’s important to consider the size of your objects when deciding to merge them.
Are there any libraries that can help with merging objects in JavaScript?
Yes, there are several libraries that can help with merging objects in JavaScript. Lodash is a popular one, offering a range of utility functions for manipulating objects and arrays, including a merge function for deep merging of objects. Another library is jQuery, which provides the $.extend() method for merging objects.
Mark is the General Manager of SitePoint.com. He loves to read and write about technology, startups, programming languages, and no code tools.