How to Merge Objects in JavaScript: A Beginner’s Guide

Are you a beginner exploring the exciting world of JavaScript? Ever wondered, “How to merge objects in JavaScript?” Well, you’re in the right place! Merging objects is a fundamental concept that every budding developer needs to grasp. Whether you’re building simple web applications or complex systems, understanding how to seamlessly combine objects can save you loads of time and effort. In this blog, we’ll break down this essential concept into easy-to-digest sections with practical examples and insights. So, let’s dive in and simplify ‘How to Merge Objects in JavaScript?’ together! Keep reading to unlock the potential of your coding skills.

Methods to Merge Objects in JavaScript

JavaScript provides multiple ways to merge objects, with the most common methods being the spread operator (...) and Object.assign().

1. Using the Spread Operator (...)

Syntax and Basic Usage:

The spread operator (...) allows you to merge objects in a clean and concise manner.

const obj1 = { name: "Alice", age: 25 };
const obj2 = { city: "New York", country: "USA" };

const mergedObj = { ...obj1, ...obj2 };

console.log(mergedObj);
// Output: { name: 'Alice', age: 25, city: 'New York', country: 'USA' }

Key Points:

  • The spread operator creates a shallow copy of objects.
  • If objects have duplicate keys, the last object’s value overwrites the previous ones.

2. Using Object.assign()

Syntax and Basic Usage:

The Object.assign() method merges multiple objects into a target object.

const obj1 = { name: "Alice", age: 25 };
const obj2 = { city: "New York", country: "USA" };

const mergedObj = Object.assign({}, obj1, obj2);

console.log(mergedObj);
// Output: { name: 'Alice', age: 25, city: 'New York', country: 'USA' }

Merging Multiple Objects:

You can merge multiple objects using Object.assign().

const obj3 = { profession: "Developer" };
const finalObj = Object.assign({}, obj1, obj2, obj3);

console.log(finalObj);
// Output: { name: 'Alice', age: 25, city: 'New York', country: 'USA', profession: 'Developer' }

Key Points:

  • Object.assign() modifies the first argument (target object).
  • To avoid modifying existing objects, always pass an empty object ({}) as the first argument.
  • Like the spread operator, it performs shallow merging (does not merge nested objects deeply).

Both methods are widely used, but the spread operator is preferred for its simplicity and readability.

Shallow vs. Deep Merging in JavaScript

When merging objects, it’s essential to understand the difference between shallow merging and deep merging, especially when dealing with nested objects.

Shallow Merging

What is a Shallow Copy?

A shallow copy creates a new object but only copies top-level properties. If the object contains nested objects (references), those references are shared, meaning modifications to nested properties affect the original object.

Example: Shallow Merge Using Spread Operator (...)

const obj1 = { name: "Alice", details: { age: 25, city: "New York" } };
const obj2 = { country: "USA" };

const shallowMerged = { ...obj1, ...obj2 };

console.log(shallowMerged);
// Output: { name: 'Alice', details: { age: 25, city: 'New York' }, country: 'USA' }

// Modifying the nested object in the merged object
shallowMerged.details.city = "Los Angeles";

console.log(obj1.details.city); // Output: "Los Angeles" (also changed in obj1)

Implications of Shallow Merging for Nested Objects:

  • Only top-level properties are copied.
  • Nested objects remain referenced, so changes affect both the original and merged objects.
  • Suitable for flat objects but problematic for deeply nested structures.

Deep Merging

What is a Deep Copy?

A deep copy creates a completely independent copy of all properties, including nested objects, ensuring changes to the new object do not affect the original.

Techniques to Perform Deep Merging

1. Using JSON.parse(JSON.stringify()) (Simple Deep Copy)

This method works for objects without functions or special types (e.g., Date, RegExp).

const obj1 = { name: "Alice", details: { age: 25, city: "New York" } };
const obj2 = { country: "USA" };

const deepMerged = JSON.parse(JSON.stringify({ ...obj1, ...obj2 }));

deepMerged.details.city = "Los Angeles";

console.log(obj1.details.city); // Output: "New York" (unchanged)

Limitations:

  • Cannot handle functions, Date, Map, Set, or circular references.

2. Using a Custom Recursive Function

For a more flexible deep merge, a recursive function is needed.

function deepMerge(target, source) {
    for (let key in source) {
        if (source[key] instanceof Object && key in target) {
            target[key] = deepMerge(target[key], source[key]);
        } else {
            target[key] = source[key];
        }
    }
    return target;
}

const obj1 = { name: "Alice", details: { age: 25, city: "New York" } };
const obj2 = { details: { city: "Los Angeles" }, country: "USA" };

const deepMerged = deepMerge({}, obj1);
deepMerge(deepMerged, obj2);

console.log(deepMerged);
// Output: { name: 'Alice', details: { age: 25, city: 'Los Angeles' }, country: 'USA' }

3. Using Lodash (_.merge)

Lodash provides a robust deep merge function.

const _ = require("lodash");

const obj1 = { name: "Alice", details: { age: 25, city: "New York" } };
const obj2 = { details: { city: "Los Angeles" }, country: "USA" };

const deepMerged = _.merge({}, obj1, obj2);

console.log(deepMerged);
// Output: { name: 'Alice', details: { age: 25, city: 'Los Angeles' }, country: 'USA' }

Why Use Lodash?

  • Handles nested objects and arrays efficiently.
  • Supports circular references and special types like Date.

Summary: Choosing the Right Merge Method

Merge TypeMethodBest for
Shallow MergeSpread (...), Object.assign()Simple objects, no nested data
Deep Merge (Basic)JSON.parse(JSON.stringify())Nested objects without functions or special types
Deep Merge (Custom)Recursive functionFull control over merging logic
Deep Merge (Lodash)_.merge()Complex objects with deep nesting

For simple objects, the spread operator is sufficient, but for deeply nested objects, custom recursive functions or Lodash should be used.

Practical Examples of Merging Objects in JavaScript

Merging objects can involve handling overlapping properties and nested objects. Below are examples demonstrating both cases.

1. Merging Objects with Overlapping Properties

When two objects have the same property, the value from the second object overwrites the first.

Example: Using the Spread Operator (...)

const obj1 = { name: "Alice", age: 25 };
const obj2 = { age: 30, city: "New York" };

const mergedObj = { ...obj1, ...obj2 };

console.log(mergedObj);
// Output: { name: 'Alice', age: 30, city: 'New York' }

Key Takeaways:

  • The age property in obj2 replaces age in obj1.
  • New properties (city) are added to the merged object.

2. Handling Nested Objects During Merge Operations

Issue with Shallow Merging

If objects have nested properties, a shallow merge does not merge deeply—it replaces the entire nested object instead.

const obj1 = { name: "Alice", details: { age: 25, city: "New York" } };
const obj2 = { details: { city: "Los Angeles" } };

const shallowMerged = { ...obj1, ...obj2 };

console.log(shallowMerged);
// Output: { name: 'Alice', details: { city: 'Los Angeles' } } ❌ (age is lost!)

Problem:

  • The entire details object from obj1 is replaced instead of merging properties inside it.

Deep Merging Using Lodash (_.merge())

Lodash provides a deep merging function to properly combine nested objects.

const _ = require("lodash");

const obj1 = { name: "Alice", details: { age: 25, city: "New York" } };
const obj2 = { details: { city: "Los Angeles" } };

const deepMerged = _.merge({}, obj1, obj2);

console.log(deepMerged);
// Output: { name: 'Alice', details: { age: 25, city: 'Los Angeles' } } ✅ (age is retained)

Custom Deep Merge Function (Without Lodash)

For projects without Lodash, you can use a recursive function to deep merge objects.

function deepMerge(target, source) {
    for (let key in source) {
        if (source[key] instanceof Object && key in target) {
            target[key] = deepMerge(target[key], source[key]);
        } else {
            target[key] = source[key];
        }
    }
    return target;
}

const obj1 = { name: "Alice", details: { age: 25, city: "New York" } };
const obj2 = { details: { city: "Los Angeles" } };

const deepMerged = deepMerge({}, obj1);
deepMerge(deepMerged, obj2);

console.log(deepMerged);
// Output: { name: 'Alice', details: { age: 25, city: 'Los Angeles' } }

Summary: Choosing the Right Merge Method

Merge TypeMethodBest for
Shallow MergeSpread (...), Object.assign()Simple objects, no nested data
Deep Merge (Basic)JSON.parse(JSON.stringify())Nested objects without functions or special types
Deep Merge (Custom)Recursive functionFull control over merging logic
Deep Merge (Lodash)_.merge()Complex objects with deep nesting

For basic objects, the spread operator works fine. However, for nested objects, deep merging methods (Lodash or recursive functions) are required.

Our AI-powered js online compiler lets users instantly write, run, and test code, making learning JavaScript seamless. With AI assistance, coding becomes intuitive and efficient, helping users understand concepts faster while providing a friendly environment for beginners to experiment and grow.

Common Pitfalls and Considerations When Merging Objects in JavaScript

Merging objects in JavaScript seems straightforward, but it can lead to unexpected issues. Below are some common pitfalls and best practices to handle them effectively.

1. Overwriting Properties with the Same Key

When two objects have the same property key, the value from the second object overwrites the first.

Example: Unexpected Overwrite

const obj1 = { name: "Alice", age: 25 };
const obj2 = { age: 30, city: "New York" };

const merged = { ...obj1, ...obj2 };

console.log(merged);
// Output: { name: 'Alice', age: 30, city: 'New York' } ❌ (age is overwritten)

Solution: Prevent Overwrites by Using Unique Keys

If you want to keep both values, rename conflicting keys before merging:

const obj2 = { ageUpdated: 30, city: "New York" };
const merged = { ...obj1, ...obj2 };

console.log(merged);
// Output: { name: 'Alice', age: 25, ageUpdated: 30, city: 'New York' } ✅ (both values retained)

2. Performance Considerations for Large Objects

Merging large objects, especially deeply nested ones, can impact performance and memory usage.

Issue: High Memory Usage in Large Objects

const largeObj1 = { data: new Array(1000000).fill("A") };
const largeObj2 = { data: new Array(1000000).fill("B") };

const merged = { ...largeObj1, ...largeObj2 };

console.log(merged.data.length); // 1000000 ❌ (data in obj1 is lost)

Solution: Use Efficient Merging Strategies

  • Avoid unnecessary deep copies when merging large datasets.
  • Use streaming or batched merging for very large objects.
  • Use Object.assign() over spread operator when memory efficiency is a concern.
const merged = Object.assign({}, largeObj1, largeObj2);

3. Ensuring Immutability During Merge Operations

Mutating original objects can lead to unexpected bugs, especially in functional programming or React state updates.

Issue: Directly Modifying the Original Object

const obj1 = { name: "Alice" };
const obj2 = { age: 30 };

Object.assign(obj1, obj2); // Mutates obj1!

console.log(obj1);
// Output: { name: 'Alice', age: 30 } ❌ (obj1 is modified)

Solution: Use Immutable Merging Techniques

To preserve immutability, always create a new object instead of modifying the existing one.

const merged = Object.assign({}, obj1, obj2);
console.log(obj1); 
// Output: { name: 'Alice' } ✅ (obj1 remains unchanged)

Alternatively, with the spread operator:

const merged = { ...obj1, ...obj2 };

For deep merges, libraries like Lodash ensure immutability:

const _ = require("lodash");

const merged = _.merge({}, obj1, obj2);

Summary: Best Practices for Safe Object Merging

PitfallSolution
Overwriting propertiesRename keys to avoid conflicts
Performance issuesAvoid unnecessary deep copies, use batch processing
Mutability risksAlways merge into a new object to prevent side effects

By following these best practices, you can merge objects safely, efficiently, and without unintended side effects.

Conclusion

Understanding how to merge objects in JavaScript empowers you to manage data effectively, a crucial skill in modern coding. For more insights and tutorials on JavaScript and other programming languages, visit Newtum. Start your coding journey today and continue exploring new challenges!

Edited and Compiled by

This blog was compiled and edited by Rasika Deshpande, who has over 4 years of experience in content creation. She’s passionate about helping beginners understand technical topics in a more interactive way.

About The Author