I know this is a bit of an old issue but the easiest solution in ES2015/ES6 I could come up with was actually quite simple, using Object.assign(),

Hopefully this helps:

/**
 * Simple object check.
 * @param item
 * @returns {boolean}
 */
export function isObject(item) {
  return (item && typeof item === 'object' && !Array.isArray(item));
}

/**
 * Deep merge two objects.
 * @param target
 * @param ...sources
 */
export function mergeDeep(target, ...sources) {
  if (!sources.length) return target;
  const source = sources.shift();

  if (isObject(target) && isObject(source)) {
    for (const key in source) {
      if (isObject(source[key])) {
        if (!target[key]) Object.assign(target, { [key]: {} });
        mergeDeep(target[key], source[key]);
      } else {
        Object.assign(target, { [key]: source[key] });
      }
    }
  }

  return mergeDeep(target, ...sources);
}

Example usage:

mergeDeep(this, { a: { b: { c: 123 } } });
// or
const merged = mergeDeep({a: 1}, { b : { c: { d: { e: 12345}}}});  
console.dir(merged); // { a: 1, b: { c: { d: [Object] } } }

You'll find an immutable version of this in the answer below.

Note that this will lead to infinite recursion on circular references. There's some great answers on here on how to detect circular references if you think you'd face this issue.

Answer from Salakar on Stack Overflow
🌐
GitHub
gist.github.com › ahtcx › 0cd94e62691f539160b32ecda18af3d6
Deep-Merge JavaScript objects with ES6 · GitHub
This solution is for iteratively merge any number of objects (it's typed with TypeScript, you might need to remove typings before using on regular JS projects): I made changes such as adding a type guard etc. to remove the Typescript errors, and also separating out mergeDeepInner to be a passed in as a function because deepMergeInner will likely change depending upon the application.
🌐
GitHub
github.com › TehShrike › deepmerge
GitHub - TehShrike/deepmerge: A library for deep (recursive) merging of Javascript objects · GitHub
A library for deep (recursive) merging of Javascript objects - TehShrike/deepmerge
Starred by 2.8K users
Forked by 216 users
Languages   JavaScript 95.8% | TypeScript 4.2%
🌐
GitHub
github.com › jonschlinkert › merge-deep
GitHub - jonschlinkert/merge-deep: Recursively merge values in a JavaScript object. · GitHub
var merge = require('merge-deep'); merge({a: {b: {c: 'c', d: 'd'}}}, {a: {b: {e: 'e', f: 'f'}}}); //=> { a: { b: { c: 'c', d: 'd', e: 'e', f: 'f' } } }
Starred by 112 users
Forked by 35 users
Languages   JavaScript
🌐
GitHub
github.com › michiweber › js-deep-merge
GitHub - michiweber/js-deep-merge: A tiny supportive script that enables deep JavaScript Object and Array merging.
The script performs a complete deep merge and merges arrays with the Array merging script. var object1 = { key1: value1 }; var object2 = { key2: value2 }; Object.deepMerge(object1, object2); // { key1: value1, key2: value2 }
Author   michiweber
Top answer
1 of 15
316

I know this is a bit of an old issue but the easiest solution in ES2015/ES6 I could come up with was actually quite simple, using Object.assign(),

Hopefully this helps:

/**
 * Simple object check.
 * @param item
 * @returns {boolean}
 */
export function isObject(item) {
  return (item && typeof item === 'object' && !Array.isArray(item));
}

/**
 * Deep merge two objects.
 * @param target
 * @param ...sources
 */
export function mergeDeep(target, ...sources) {
  if (!sources.length) return target;
  const source = sources.shift();

  if (isObject(target) && isObject(source)) {
    for (const key in source) {
      if (isObject(source[key])) {
        if (!target[key]) Object.assign(target, { [key]: {} });
        mergeDeep(target[key], source[key]);
      } else {
        Object.assign(target, { [key]: source[key] });
      }
    }
  }

  return mergeDeep(target, ...sources);
}

Example usage:

mergeDeep(this, { a: { b: { c: 123 } } });
// or
const merged = mergeDeep({a: 1}, { b : { c: { d: { e: 12345}}}});  
console.dir(merged); // { a: 1, b: { c: { d: [Object] } } }

You'll find an immutable version of this in the answer below.

Note that this will lead to infinite recursion on circular references. There's some great answers on here on how to detect circular references if you think you'd face this issue.

2 of 15
254

You can use Lodash merge:

var object = {
  'a': [{ 'b': 2 }, { 'd': 4 }]
};

var other = {
  'a': [{ 'c': 3 }, { 'e': 5 }]
};

console.log(_.merge(object, other));
// => { 'a': [{ 'b': 2, 'c': 3 }, { 'd': 4, 'e': 5 }] }
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.21/lodash.min.js"></script>

🌐
GitHub
github.com › JLCarveth › deep-merge
GitHub - JLCarveth/deep-merge: Small library to recursively merge nested Javascript Objects
A small tool used to recursively merge nested javascript objects. The primary function of this module is merge(a,b). This function takes two objects, a and b, and returns a new object with merged properties from both parameters.
Author   JLCarveth
🌐
GitHub
github.com › fastify › deepmerge
GitHub - fastify/deepmerge: Merges the enumerable properties of two or more objects deeply. Fastest implementation of deepmerge · GitHub
isMergeableObject (function, optional) - provide a function, which must return true if the object should be merged, default is isMergeableObject from this module · onlyDefinedProperties (boolean, optional) - if true, properties with undefined in the source will not overwrite existing values from the target, default is false · const deepmerge = require('@fastify/deepmerge')() const result = deepmerge({a: 'value'}, { b: 404 }) console.log(result) // {a: 'value', b: 404 }
Starred by 120 users
Forked by 18 users
Languages   JavaScript 87.6% | TypeScript 12.4%
🌐
GitHub
gist.github.com › Salakar › 1d7137de9cb8b704e48a
ES6/ES2015 Object deep merge · GitHub
April 5, 2019 - /** * Simple is object check. * @param item * @returns {boolean} */ export function isObject(item) { return (item && typeof item === 'object' && !Array.isArray(item) && item !== null); } /** * Deep merge two objects.
Find elsewhere
🌐
GitHub
github.com › topics › deepmerge
deepmerge · GitHub Topics
Merges the enumerable properties of two or more objects deeply. Fastest implementation of deepmerge ... Uniquely flexible and light-weight utility for cloning and deep (recursive) merging of JavaScript objects.
🌐
GitHub
github.com › eclifford › n-deep-merge
GitHub - eclifford/n-deep-merge: deep merge a collection of javascript objects and arrays
deep merge a collection of javascript objects and arrays - GitHub - eclifford/n-deep-merge: deep merge a collection of javascript objects and arrays
Starred by 2 users
Forked by 3 users
Languages   JavaScript 100.0% | JavaScript 100.0%
🌐
Jhildenbiddle
jhildenbiddle.github.io › mergician
Mergician - a uniquely flexible and light-weight utility for deep (recursive) merging/cloning of JavaScript objects
Mergician is a uniquely flexible and light-weight utility for deep (recursive) merging/cloning of JavaScript objects. Unlike native methods and other merge/clone utilities, Mergician provides advanced options for customizing the merge/clone process. These options make it easy to inspect, filter, ...
🌐
GitHub
github.com › topics › merge
merge · GitHub Topics · GitHub
Uniquely flexible and light-weight utility for cloning and deep (recursive) merging of JavaScript objects. Supports descriptor values, accessor functions, and custom prototypes.
🌐
GitHub
github.com › Raynos › deep-merge
GitHub - Raynos/deep-merge: Deep merge objects with custom merging logic
var DeepMerge = require("deep-merge") var assert = require("assert") var merge = DeepMerge(function mergeStrategy(target, source, key) { return [].concat(target, source) }) var res = merge({ foo: ["hello"] }, { foo: "goodbye" }) assert.deepEqual(res, { foo: ["hello", "goodbye"] }) By default objects will recursely call your mergeStrategy on your the values for a key and construct a new object with the key and the value returned from your merge
Starred by 17 users
Forked by 6 users
Languages   JavaScript 100.0% | JavaScript 100.0%
🌐
GitHub
github.com › tracker1 › deep-merge
GitHub - tracker1/deep-merge: Deep merge JavaScript objects
// CJS const deepMerge = require('@tracker1/deep-merge'); // ESM import deepMerge from '@tracker1/deep-merge'; const a = { a: 'foo', b: { c:'bar', d:'baz' }, e: { f: 'to be replaced' } }; const b = { x: 'biff', b: { d: 'bazzer' }, e: { __REPLACE__: 'deep replaces e', g: 'new value' } }; console.log(deepMerge(a, b)); // { // a: 'foo', // b: { c: 'bar', d: 'bazzer' }, // e: { g: 'new value' }, // x: 'biff' // } Objects with a truthy __REPLACE__ property will replace the original entirely (without the __REPLACE__ property);
Author   tracker1
🌐
GitHub
github.com › topics › deep-merge
deep-merge · GitHub Topics · GitHub
Uniquely flexible and light-weight utility for cloning and deep (recursive) merging of JavaScript objects. Supports descriptor values, accessor functions, and custom prototypes.
🌐
GitHub
github.com › 75lb › deep-merge
GitHub - 75lb/deep-merge: Deep merge config objects
Deep-merge the values of one object structure into another. Similar to Object.assign() except it processes the full depth of the object structure, not only the top level.
Author   75lb
🌐
GitHub
github.com › etc-tiago › deep-merge-object
GitHub - etc-tiago/deep-merge-object: Lightweight Javascript deep merge object
const objA = { position: 'relative', padding: '8px 12px 6px 30px', fontSize: 17, lineHeight: '20px', height: 34, borderRadius: '0', selectors: { '&:before': { content: "''", width: 22, height: 22, border: '2px solid #707c90', position: 'absolute', top: '50%', left: 0, transform: 'translateY(-50%)', }, }, }; const objB = { selectors: { '&:before': { borderRadius: '50%' } } }; console.log(objectMerge(objA, objB)); /* { position: 'relative', padding: '8px 12px 6px 30px', fontSize: 17, lineHeight: '20px', height: 34, borderRadius: '0', selectors: { '&:before': { content: "''", width: 22, height: 22, border: '2px solid #707c90', position: 'absolute', top: '50%', left: 0, transform: 'translateY(-50%)', borderRadius: '50%', }, }, } */
Starred by 2 users
Forked by 3 users
Languages   TypeScript 77.0% | JavaScript 23.0% | TypeScript 77.0% | JavaScript 23.0%
🌐
npm
npmjs.com › package › deepmerge
deepmerge - npm
March 16, 2023 - There are multiple ways to merge two arrays, below are a few examples but you can also create your own custom function. Your arrayMerge function will be called with three arguments: a target array, the source array, and an options object with these properties:
      » npm install deepmerge
    
Published   Mar 16, 2023
Version   4.3.1