Merging JavaScript Objects
Often in JavaScript, you’ll need to combine the properties of two or more objects into a single object. This process, known as merging, is a common task in many applications. There are several ways to achieve this, ranging from basic iteration to modern ECMAScript features. This tutorial will explore these methods, providing examples and explaining the trade-offs of each approach.
Basic Iteration (ES5 Compatible)
For older JavaScript environments (ES5 and earlier), a simple for...in
loop provides a way to merge objects. This approach iterates through the properties of the source object and copies them to the target object.
function mergeObjects(target, source) {
for (const key in source) {
if (source.hasOwnProperty(key)) { // Ensure the property belongs to the object itself
target[key] = source[key];
}
}
return target;
}
const obj1 = { a: 1, b: 2 };
const obj2 = { c: 3, d: 4 };
const mergedObj = mergeObjects(obj1, obj2);
console.log(mergedObj); // Output: { a: 1, b: 2, c: 3, d: 4 }
Important: The hasOwnProperty
check is crucial. It prevents inheriting properties from the prototype chain, ensuring you only merge properties directly defined on the object.
Object.assign()
(ES6/ES2015)
ECMAScript 2015 (ES6) introduced Object.assign()
, a dedicated method for merging objects. It copies all enumerable own properties from one or more source objects to a target object.
const obj1 = { a: 1, b: 2 };
const obj2 = { c: 3, d: 4 };
const mergedObj = Object.assign({}, obj1, obj2); // Pass an empty object as the target to create a new object
console.log(mergedObj); // Output: { a: 1, b: 2, c: 3, d: 4 }
// Modifying the first argument will mutate it
const obj3 = { x: 10 };
Object.assign(obj3, { y: 20, z: 30 });
console.log(obj3); // Output: { x: 10, y: 20, z: 30 }
Key points:
Object.assign()
mutates the first argument (the target object) unless you pass an empty object{}
as the target, which effectively creates a new object.- Properties in later source objects overwrite properties with the same key in earlier ones.
- It only copies enumerable and own properties.
Spread Syntax (ES2018)
ECMAScript 2018 (ES2018) introduced the spread syntax (...
), which provides a concise way to merge objects. It’s often considered the most elegant and readable approach.
const obj1 = { a: 1, b: 2 };
const obj2 = { c: 3, d: 4 };
const mergedObj = { ...obj1, ...obj2 };
console.log(mergedObj); // Output: { a: 1, b: 2, c: 3, d: 4 }
Advantages of Spread Syntax:
- Immutability: It creates a new object, leaving the original objects unchanged.
- Readability: It’s very concise and easy to understand.
- Flexibility: You can merge any number of objects.
Important Note: Like Object.assign()
, properties in later objects overwrite those with the same key in earlier objects.
Recursive Merge
In some cases, you might need to merge objects that contain nested objects. A simple merge won’t suffice; you need a recursive approach to merge the nested objects as well.
function mergeRecursive(target, source) {
for (const key in source) {
if (source.hasOwnProperty(key)) {
if (typeof source[key] === 'object' && source[key] !== null && !Array.isArray(source[key])) {
if (typeof target[key] !== 'object' || target[key] === null || Array.isArray(target[key])) {
target[key] = {};
}
mergeRecursive(target[key], source[key]);
} else {
target[key] = source[key];
}
}
}
return target;
}
const obj1 = { a: 1, b: { x: 2, y: 3 } };
const obj2 = { b: { y: 4, z: 5 }, c: 6 };
const mergedObj = mergeRecursive(obj1, obj2);
console.log(mergedObj);
// Output: { a: 1, b: { x: 2, y: 4, z: 5 }, c: 6 }
This recursive function traverses the objects, merging nested objects and copying primitive values. It handles cases where a property exists in both objects but is not an object itself, ensuring that the value is overwritten correctly.
Choosing the Right Approach
- ES5 compatibility: Use the basic iteration method.
- Simplicity and immutability: Spread syntax is the preferred choice for most modern JavaScript projects.
- Browser support: Ensure sufficient browser support for the chosen method or consider polyfilling older features.
- Deep merging: If you need to merge nested objects, use the recursive merge function.