Back to Home
Objects

How to Deep Merge Objects

Recursively merge nested objects

Quick Answer (2024 ES6+ Way)

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

Live Example

javascript
function deepMerge(target, ...sources) {
  if (!sources.length) return target;
  const source = sources.shift();
  
  if (typeof target === 'object' && typeof source === 'object') {
    for (const key in source) {
      if (typeof source[key] === 'object' && !Array.isArray(source[key])) {
        if (!target[key]) Object.assign(target, { [key]: {} });
        deepMerge(target[key], source[key]);
      } else {
        Object.assign(target, { [key]: source[key] });
      }
    }
  }
  
  return deepMerge(target, ...sources);
}

const defaults = {
  user: { name: 'Guest', settings: { theme: 'light' } }
};

const custom = {
  user: { settings: { theme: 'dark', fontSize: 14 } }
};

const merged = deepMerge({}, defaults, custom);
console.log(merged);

Common Variations

Merge Arrays
javascript
function mergeArrays(target, source) {
  if (Array.isArray(source)) {
    return Array.isArray(target) 
      ? [...target, ...source]
      : source;
  }
  return deepMerge(target, source);
}
Custom Merger
javascript
function merge(target, source, customizer) {
  return Object.keys(source).reduce((acc, key) => {
    const merged = customizer(target[key], source[key], key);
    acc[key] = merged !== undefined ? merged : source[key];
    return acc;
  }, { ...target });
}

❌ Don't Do This (Outdated Way)

Avoid Object.assign for nested objects

javascript
// DON'T DO THIS - only shallow merge
const merged = Object.assign({}, obj1, obj2);

Browser Support

Works in all modern browsers (ES2015+)

#objects#merge#deep