How to Deep Merge Two Objects in JavaScript?

In JavaScript, a deep merge of two objects means creating a new object by combining properties recursively, including nested objects. Unlike a simple merge, it ensures that no nested properties are lost during the merge, which only replaces top-level properties. In this article, we will look at several ways of performing a deep merge of two objects, with code and explanations.

Approaches to Deep Merge

Manual Recursive Function

A custom function provides complete control over how the merge operates.

Example

function deepMerge(obj1, obj2) {
    const result = { ...obj1 }; // Start with a shallow copy of obj1

    for (const key in obj2) {
        if (obj2[key] && typeof obj2[key] === "object" && !Array.isArray(obj2[key])) {
            result[key] = deepMerge(result[key] || {}, obj2[key]);
        } else {
            result[key] = obj2[key];
        }
    }

    return result;
}

// Example usage
const obj1 = { name: "Pankaj", details: { age: 21, skills: ["JavaScript"] } };
const obj2 = { details: { age: 22, location: "India" }, hobbies: ["Coding"] };

const merged = deepMerge(obj1, obj2);
console.log(merged);

Output

{
  name: "Pankaj",
  details: { age: 22, skills: ["JavaScript"], location: "India" },
  hobbies: ["Coding"]
}

Using Lodash's merge Method

Lodash is a popular utility library for JavaScript. Its merge method makes it easy to merge objects deep.

Example

const _ = require('lodash');

const obj1 = { name: "Pankaj", details: { age: 21, skills: ["JavaScript"] } };
const obj2 = { details: { age: 22, location: "India" }, hobbies: ["Coding"] };

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

Output

{
  name: "Pankaj",
  details: { age: 22, skills: ["JavaScript"], location: "India" },
  hobbies: ["Coding"]
}

Using the Spread Operator with Recursion

The spread operator (...) can be combined with recursion for deep merging.

Example

function deepMerge(obj1, obj2) {
    return {
        ...obj1,
        ...Object.keys(obj2).reduce((acc, key) => {
            acc[key] = 
                obj1[key] && typeof obj2[key] === "object" && !Array.isArray(obj2[key])
                ? deepMerge(obj1[key], obj2[key])
                : obj2[key];
            return acc;
        }, {})
    };
}

// Example usage
const obj1 = { name: "Pankaj", details: { age: 21, skills: ["JavaScript"] } };
const obj2 = { details: { age: 22, location: "India" }, hobbies: ["Coding"] };

const merged = deepMerge(obj1, obj2);
console.log(merged);

Output

{
  name: "Pankaj",
  details: { age: 22, skills: ["JavaScript"], location: "India" },
  hobbies: ["Coding"]
}

Using Object.assign with Recursion

Object.assign can be used for merging but it needs recursion for deep merges.

Example

function deepMerge(obj1, obj2) {
    const result = Object.assign({}, obj1);

    for (const key in obj2) {
        if (obj2[key] && typeof obj2[key] === "object" && !Array.isArray(obj2[key])) {
            result[key] = deepMerge(result[key] || {}, obj2[key]);
        } else {
            result[key] = obj2[key];
        }
    }

    return result;
}

// Example usage
const obj1 = { name: "Pankaj", details: { age: 21, skills: ["JavaScript"] } };
const obj2 = { details: { age: 22, location: "India" }, hobbies: ["Coding"] };

const merged = deepMerge(obj1, obj2);
console.log(merged);

Output

{
  name: "Pankaj",
  details: { age: 22, skills: ["JavaScript"], location: "India" },
  hobbies: ["Coding"]
}

Comparison

Method Dependencies Performance Complexity
Manual Recursive None Good Medium
Lodash merge Lodash library Very good Low
Spread + Recursion None Good High
Object.assign + Recursion None Good Medium

Conclusion

For deep merging objects, use Lodash's merge method for production code due to its robustness. For custom implementations, the manual recursive function offers the best balance of readability and control.

Updated on: 2026-03-15T23:19:01+05:30

1K+ Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements