By JC Grubbs


2008-10-05 00:30:54 8 Comments

I need to be able to merge two (very simple) JavaScript objects at runtime. For example I'd like to:

var obj1 = { food: 'pizza', car: 'ford' }
var obj2 = { animal: 'dog' }

obj1.merge(obj2);

//obj1 now has three properties: food, car, and animal

Does anyone have a script for this or know of a built in way to do this? I do not need recursion, and I do not need to merge functions, just methods on flat objects.

30 comments

@space97 2019-11-13 22:24:30

It seems like this should be all you need:

var obj1 = { food: 'pizza', car: 'ford' }
var obj2 = { animal: 'dog' }

var obj1 = { ...obj1, ...obj2 }

After that obj1 should now have the following value:

{food: "pizza", car: "ford", animal: "dog"}

@Vahid Akhtar 2019-10-14 05:13:54

merge two object using Object.assign and spread operator.

Wrong way(Modify original object because targeting o1)

var o1 = { X: 10 };
var o2 = { Y: 20 };
var o3 = { Z: 30 };
var merge = Object.assign(o1, o2, o3);
console.log(merge)  // {X:10, Y:20, Z:30}
console.log(o1)     // {X:10, Y:20, Z:30}

Right ways

  • Object.assign({}, o1, o2, o3) ==> targeting new object

  • {...o1, ...o2, ...o3} ==> spreading objects

var o1 = { X: 10 };
var o2 = { Y: 20 };
var o3 = { Z: 30 };

console.log('Does not modify original objects because target {}');
var merge = Object.assign({}, o1, o2, o3);
console.log(merge); // { X: 10, Y: 20, Z: 30 }
console.log(o1)

console.log('Does not modify original objects')
var spreadMerge = {...o1, ...o2, ...o3};
console.log(spreadMerge);
console.log(o1);

@John Millikin 2008-10-05 00:33:25

ECMAScript 2018 Standard Method

You would use object spread:

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

/** There's no limit to the number of objects you can merge.
 *  Later properties overwrite earlier properties with the same name. */
const allRules = {...obj1, ...obj2, ...obj3};

Here is also the MDN documentation for this syntax, and if you're using babel- you'll need this plugin for it to work.

ECMAScript 2015 (ES6) Standard Method

/* For the case in question, you would do: */
Object.assign(obj1, obj2);

/** There's no limit to the number of objects you can merge.
 *  All objects get merged into the first object. 
 *  Only the object in the first argument is mutated and returned.
 *  Later properties overwrite earlier properties with the same name. */
const allRules = Object.assign({}, obj1, obj2, obj3, etc);

(see MDN JavaScript Reference)


Method for ES5 and Earlier

for (var attrname in obj2) { obj1[attrname] = obj2[attrname]; }

Note that this will simply add all attributes of obj2 to obj1 which might not be what you want if you still want to use the unmodified obj1.

If you're using a framework that craps all over your prototypes then you have to get fancier with checks like hasOwnProperty, but that code will work for 99% of cases.

Example function:

/**
 * Overwrites obj1's values with obj2's and adds obj2's if non existent in obj1
 * @param obj1
 * @param obj2
 * @returns obj3 a new object based on obj1 and obj2
 */
function merge_options(obj1,obj2){
    var obj3 = {};
    for (var attrname in obj1) { obj3[attrname] = obj1[attrname]; }
    for (var attrname in obj2) { obj3[attrname] = obj2[attrname]; }
    return obj3;
}

@Xiè Jìléi 2010-10-24 10:56:19

This doesn't work if objects have same name attributes, and you would also want to merge the attributes.

@Jay Taylor 2011-06-02 15:39:52

This only does a shallow copy/merge. Has the potential to clobber a lot of elements.

@thejonwithnoh 2016-05-07 04:18:07

​+1 for acknowledging that some poor souls are forced to use frameworks that crap all over their prototypes...

@scones 2016-05-15 19:15:20

Overwrites obj1's values with obj2's and adds obj2's if non existent in obj1 this is not correct with the shown implementation of building a new object.

@Jon 2016-11-01 12:49:42

@scones I think he's talking about how the two are merged. I.e. Overwrites obj1's values (in obj3) with obj2's and adds obj2's (to obj3) if non existent in obj1

@lifeisfoo 2017-07-22 09:21:51

Keep in mind Object.assign(target, ...sources) precedence: properties in the target object will be overwritten by properties in the sources if they have the same key. Later sources' properties will similarly overwrite earlier ones. See the doc for more information.

@morgler 2018-01-10 20:20:24

This didn't work for me because of "Therefore it assigns properties versus just copying or defining new properties. This may make it unsuitable for merging new properties into a prototype if the merge sources contain getters." (developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…‌​). I had to use var merged = {...obj1, ...obj2}.

@Dan 2019-03-13 11:39:57

Why doesn't {...obj1, {animal: 'dog'}} work?

@backslash112 2019-04-11 21:13:19

@Ze'ev {...obj1, ...{animal: 'dog'}}

@lu1s 2019-04-29 17:32:25

I would like to think that Object.assign from ES6 is the way to go for cross-functionality. The question is probably not so clear for all, but for me it works nice by assigning new values if the properties are named the same as the target's.

@Andy 2019-05-22 20:28:45

"There's no limit to the number of arguments you can merge" there's one caveat -- the number of arguments to a function call is limited by most JavaScript VMs, so you would have to use multiple Object.assign calls beyond a certain point

@Madacol 2019-08-29 17:08:47

Just to make it clear. Object.assign(obj1, obj2) merges obj2 into obj1, so it preserves obj1 references, while let merged = {...obj1, ...obj2} creates a new object from scratch.

@ToolmakerSteve 2019-10-03 20:33:15

@Madacol - Good point. Also, Object.assign({}, obj1, obj2) would be how to useassign syntax to create a new object.

@Minh Nghĩa 2019-10-14 03:44:35

What can I do if I want to merge but merged is a const variable?

@George WS 2019-10-22 16:59:39

@Dan Alternatively (to @backslash112's approach), {...obj1, animal: 'dog'}

@Legends 2018-03-20 21:41:44

**Merging objects is simple using Object.assign or the spread ... operator **

var obj1 = { food: 'pizza', car: 'ford' }
var obj2 = { animal: 'dog', car: 'BMW' }
var obj3 = {a: "A"}


var mergedObj = Object.assign(obj1,obj2,obj3)
 // or using the Spread operator (...)
var mergedObj = {...obj1,...obj2,...obj3}

console.log(mergedObj);

The objects are merged from right to left, this means that objects which have identical properties as the objects to their right will be overriden.

In this example obj2.car overrides obj1.car

@Bekim Bacaj 2017-04-20 17:31:53

The Merge Of JSON Compatible JavaScript Objects

I encourage the use and utilization of nondestructive methods that don't modify the original source, 'Object.assign' is a destructive method and it also happens to be not so production friendly because it stops working on earlier browsers and you have no way of patching it cleanly, with an alternative.

Merging JS Objects will always be out of reach, or incomplete, whatever the solution. But merging JSON compliant compatible objects is just one step away from being able to write a simple and portable piece of code of a nondestructive method of merging series of JS Objects into a returned master containing all the unique property-names and their corresponding values synthesized in a single master object for the intended purpose.

Having in mind that MSIE8 is the first browser to have added a native support for the JSON object is a great relief, and reusing the already existing technology, is always a welcomed opportunity.

Restricting your code to JSON complant standard objects, is more of an advantage, than a restriction - since these objects can also be transmitted over the Internet. And of course for those who would like a deeper backward compatibility there's always a json plug., whose methods can easily be assigned to a JSON variable in the outer code without having to modify or rewrite the method in use.

function Merge( ){
    var a = [].slice.call( arguments ), i = 0;
        while( a[i] )a[i] = JSON.stringify( a[i++] ).slice( 1,-1 );
        return JSON.parse( "{"+ a.join() +"}" );
    }

(Of course one can always give it a more meaningful name, which I haven't decided yet; should probably name it JSONmerge)

The use case:

var master = Merge( obj1, obj2, obj3, ...objn );

Now, contrary to the Object.assign this leaves all objects untouched and in their original state (in case you've done something wrong and need to reorder the merging objects or be able to use them separately for some other operation before merging them again).

Tthe number of the Merge arguments is also limited only by the arguments length limit [which is huge]. The natively supported JSON parse / stringify is already machine optimized, meaning: it should be faster than any scripted form of JS loop. The iteration over given arguments, is being done using the while - proven to be the fastest loop in JS.

It doesn't harm to briefly mention the fact we already know that duplicate properties of the unique object labels (keys) will be overwritten by the later object containing the same key label, which means you are in control of which property is taking over the previous by simply ordering or reordering the arguments list. And the benefit of getting a clean and updated master object with no dupes as a final output.

;
var obj1 = {a:1}, obj2 = {b:2}, obj3 = {c:3}
;
function Merge( ){
    var a = [].slice.call( arguments ), i = 0;
        while( a[i] )a[i] = JSON.stringify( a[i++] ).slice( 1,-1 );
        return JSON.parse( "{"+ a.join() +"}" );
    }
;
var master = Merge( obj1, obj2, obj3 )
;
console.log( JSON.stringify( master ) )
;

@Paweł Otto 2019-03-14 06:55:09

ES2018/TypeScript: Many answers are OK but I've come up with a more elegant solution to this problem when you need to merge two objects without overwriting overlapping object keys.

My function also accepts unlimited number of objects to merge as function arguments:

(I'm using TypeScript notation here, feel free to delete the :object[] type in the function argument if you're using plain JavaScript).

const merge = (...objects: object[]) => {
  return objects.reduce((prev, next) => {
    Object.keys(prev).forEach(key => {
      next[key] = { ...next[key], ...prev[key] }
    })
    return next
  })
}

@Chris Stryczynski 2019-04-04 11:54:45

This does not seem to work? typescript-play.js.org/#code/…

@Tejas Savaliya 2019-01-17 11:30:02

let obj1 = {a:1, b:2};
let obj2 = {c:3, d:4};
let merged = {...obj1, ...obj2};
console.log(merged);

@gildniy 2018-11-07 13:16:06

With the following helper, you can merge two objects into one new object:

function extend(obj, src) {
    for (var key in src) {
        if (src.hasOwnProperty(key)) obj[key] = src[key];
    }
    return obj;
}

// example
var a = { foo: true }, b = { bar: false };
var c = extend(a, b);

console.log(c);
// { foo: true, bar: false }

This is typically useful when merging an options dict with the default settings in a function or a plugin.

If support for IE 8 is not required, you may use Object.keys for the same functionality instead:

function extend(obj, src) {
    Object.keys(src).forEach(function(key) { obj[key] = src[key]; });
    return obj;
}

This involves slightly less code and is a bit faster.

@Tính Ngô Quang 2018-09-18 01:55:43

var obj1 = { food: 'pizza', car: 'ford' }
var obj2 = { animal: 'dog' }

// result
result: {food: "pizza", car: "ford", animal: "dog"}

Using jQuery.extend() - Link

// Merge obj1 & obj2 to result
var result1 = $.extend( {}, obj1, obj2 );

Using _.merge() - Link

// Merge obj1 & obj2 to result
var result2 = _.merge( {}, obj1, obj2 );

Using _.extend() - Link

// Merge obj1 & obj2 to result
var result3 = _.extend( {}, obj1, obj2 );

Using Object.assign() ECMAScript 2015 (ES6) - Link

// Merge obj1 & obj2 to result
var result4 = Object.assign( {}, obj1, obj2 );

Output of all

obj1: { animal: 'dog' }
obj2: { food: 'pizza', car: 'ford' }
result1: {food: "pizza", car: "ford", animal: "dog"}
result2: {food: "pizza", car: "ford", animal: "dog"}
result3: {food: "pizza", car: "ford", animal: "dog"}
result4: {food: "pizza", car: "ford", animal: "dog"}

@Avdi 2008-10-05 03:56:40

jQuery also has a utility for this: http://api.jquery.com/jQuery.extend/.

Taken from the jQuery documentation:

// Merge options object into settings object
var settings = { validate: false, limit: 5, name: "foo" };
var options  = { validate: true, name: "bar" };
jQuery.extend(settings, options);

// Now the content of settings object is the following:
// { validate: true, limit: 5, name: "bar" }

The above code will mutate the existing object named settings.


If you want to create a new object without modifying either argument, use this:

var defaults = { validate: false, limit: 5, name: "foo" };
var options = { validate: true, name: "bar" };

/* Merge defaults and options, without modifying defaults */
var settings = $.extend({}, defaults, options);

// The content of settings variable is now the following:
// {validate: true, limit: 5, name: "bar"}
// The 'defaults' and 'options' variables remained the same.

@webmat 2011-05-04 16:01:48

Careful: the variable "settings" will be modified, though. jQuery doesn't return a new instance. The reason for this (and for the naming) is that .extend() was developed to extend objects, rather than to munge stuff together. If you want a new object (e.g. settings is defaults you don't want to touch), you can always jQuery.extend({}, settings, options);

@Mike Starov 2011-06-02 20:30:17

Right on! Thanks a bunch. As previous comment stated it is poorly named. i searched jQuery docs back and fourth and did not run into it.

@vol7ron 2011-06-09 21:09:38

Mind you, jQuery.extend also has a deep (boolean) setting. jQuery.extend(true,settings,override), which is important if a property in settings holds an object and override only has part of that object. Instead of removing the unmatched properties, the deep setting will only update where it exists. The default is false.

@Brendon-Van-Heyzen 2011-06-30 15:24:33

for people who use dojo its dojo.mixin(object,object);

@Петър Петров 2012-03-22 13:44:36

And this is the best way to merge second object with the base object. This is exactly what you want - default iotions agets merged with user's options. Default options is now the result of the merge operation.

@Derek Greer 2014-05-20 18:43:01

Gee willikers, they really did a good job naming this. If you search for how to extend a Javascript object it comes right up! You might not hit upon it though if you are trying to fuse or stitch together Javascript objects.

@CrazyMerlin 2016-08-11 18:01:18

Don't tell people to consider using a library method when a couple of lines of vanilla JS will do what they want. There was a time before jQuery!

@Simon Ordo 2016-10-17 16:12:24

Is this intended to also remove objects from "options" if they aren't present in "defaults" ?

@ToolmakerSteve 2019-10-03 20:42:10

@SimonOrdo. Not sure what your question means. The concepts "merge" or "extend" have nothing to do with "removing" anything from anywhere. But to clarify, only the first parameter of "extend" is changed: it gains all members of all other parameters (but if a member has same name, only the one from the last parameter is kept).

@vsync 2011-11-01 10:20:14

function extend(o, o1, o2){
    if( !(o instanceof Object) ) o = {};

    copy(o, o1);
    if( o2 )
        copy(o, o2)

    function isObject(obj) {
        var type = Object.prototype.toString.call(obj);
        return obj === Object(obj) && type != '[object Array]' && type != '[object Function]';
    };

    function copy(a,b){
        // copy o2 to o
        for( var key in b )
            if( b.hasOwnProperty(key) ){
                if( isObject(b[key]) ){
                    if( !isObject(a[key]) )
                        a[key] = Object.assign({}, b[key]); 
                    else copy(a[key], b[key])
                }
                else
                    a[key] = b[key];
            }
    }

    return o;
};


var o1 = {a:{foo:1}, b:1},
    o2 = {a:{bar:2}, b:[1], c:()=>{}},
    newMerged = extend({}, o1, o2);
    
console.log( newMerged )
console.log( o1 )
console.log( o2 )

@pancake 2012-04-24 05:02:50

This falls over if o2 contains any properties that don't already exist in o1, which is exactly why Markus has the try/catch you've removed. Your example only works because all of o2's properties already exist in o1. So, this isn't a merge, and it isn't better!

@vsync 2013-09-03 12:16:23

no it doesn't fail, I've just tried what you've said with success.

@mindplay.dk 2016-04-04 15:51:15

One should note that the function is destructive and obj1 as well as any objects nested inside it will be modified, which may or may not be what you wanted. I renamed the function and arguments to applyProperties(target, source) myself for clarity.

@vsync 2016-04-04 18:06:56

@mindplay.dk - what do you mean destructive? the point is to merge o2 into o1, not to create a new (third) object of o1 merged with o2. I answered the exact question

@mindplay.dk 2016-04-09 14:48:42

@vsync destructive in the sense that e.g. Array.sort() is destructive and Array.slice() isn't - it's not a criticism, just pointing out a fact :-)

@vsync 2016-04-09 16:01:14

@mindplay.dk - it was explicitly asked in the question to merge one object into the other, overriding the first, so obviously it is destructive by the nature of the question at hand. for a non-destructive answer one must go to another answer's page

@aircraft 2018-05-31 13:11:32

We can crate a empty object, and combine them by for-loop:

var obj1 = {
  id: '1',
  name: 'name'
}

var obj2 = {
  c: 'c',
  d: 'd'
}

var obj3 = {}

for (var attrname in obj1) { obj3[attrname] = obj1[attrname]; }
for (var attrname in obj2) { obj3[attrname] = obj2[attrname]; }


console.log( obj1, obj2, obj3)

@Logan 2018-05-01 18:44:14

Wow.. this is the first StackOverflow post I've seen with multiple pages. Apologies for adding another "answer"

This method is for ES5 & Earlier - there are plenty of other answers addressing ES6.

I did not see any "deep" object merging utilizing the arguments property. Here is my answer - compact & recursive, allowing unlimited object arguments to be passed:

function extend() {
    for (var o = {}, i = 0; i < arguments.length; i++) {
        // if (arguments[i].constructor !== Object) continue;
        for (var k in arguments[i]) {
            if (arguments[i].hasOwnProperty(k)) {
                o[k] = arguments[i][k].constructor === Object ? extend(o[k] || {}, arguments[i][k]) : arguments[i][k];
            }
        }
    }
    return o;
}

The portion that is commented out is optional .. it will simply skip arguments passed that are not objects (preventing errors).

Example:

extend({
    api: 1,
    params: {
        query: 'hello'
    }
}, {
    params: {
        query: 'there'
    }
});

// outputs {api: 1, params: {query: 'there'}}

This answer is now but a drop in the ocean ...

@Snoozer Man 2012-01-06 21:47:46

Based on Markus' and vsync' answer, this is an expanded version. The function takes any number of arguments. It can be used to set properties on DOM nodes and makes deep copies of values. However, the first argument is given by reference.

To detect a DOM node, the isDOMNode() function is used (see Stack Overflow question JavaScript isDOM — How do you check if a JavaScript Object is a DOM Object?)

It was tested in Opera 11, Firefox 6, Internet Explorer 8 and Google Chrome 16.

Code

function mergeRecursive() {

  // _mergeRecursive does the actual job with two arguments.
  var _mergeRecursive = function (dst, src) {
    if (isDOMNode(src) || typeof src !== 'object' || src === null) {
      return dst;
    }

    for (var p in src) {
      if (!src.hasOwnProperty(p))
        continue;
      if (src[p] === undefined)
        continue;
      if ( typeof src[p] !== 'object' || src[p] === null) {
        dst[p] = src[p];
      } else if (typeof dst[p]!=='object' || dst[p] === null) {
        dst[p] = _mergeRecursive(src[p].constructor===Array ? [] : {}, src[p]);
      } else {
        _mergeRecursive(dst[p], src[p]);
      }
    }
    return dst;
  }

  // Loop through arguments and merge them into the first argument.
  var out = arguments[0];
  if (typeof out !== 'object' || out === null)
    return out;
  for (var i = 1, il = arguments.length; i < il; i++) {
    _mergeRecursive(out, arguments[i]);
  }
  return out;
}

Some examples

Set innerHTML and style of a HTML Element

mergeRecursive(
  document.getElementById('mydiv'),
  {style: {border: '5px solid green', color: 'red'}},
  {innerHTML: 'Hello world!'});

Merge arrays and objects. Note that undefined can be used to preserv values in the lefthand array/object.

o = mergeRecursive({a:'a'}, [1,2,3], [undefined, null, [30,31]], {a:undefined, b:'b'});
// o = {0:1, 1:null, 2:[30,31], a:'a', b:'b'}

Any argument not beeing a JavaScript object (including null) will be ignored. Except for the first argument, also DOM nodes are discarded. Beware that i.e. strings, created like new String() are in fact objects.

o = mergeRecursive({a:'a'}, 1, true, null, undefined, [1,2,3], 'bc', new String('de'));
// o = {0:'d', 1:'e', 2:3, a:'a'}

If you want to merge two objects into a new (without affecting any of the two) supply {} as first argument

var a={}, b={b:'abc'}, c={c:'cde'}, o;
o = mergeRecursive(a, b, c);
// o===a is true, o===b is false, o===c is false

Edit (by ReaperSoon):

To also merge arrays

function mergeRecursive(obj1, obj2) {
  if (Array.isArray(obj2)) { return obj1.concat(obj2); }
  for (var p in obj2) {
    try {
      // Property in destination object set; update its value.
      if ( obj2[p].constructor==Object ) {
        obj1[p] = mergeRecursive(obj1[p], obj2[p]);
      } else if (Array.isArray(obj2[p])) {
        obj1[p] = obj1[p].concat(obj2[p]);
      } else {
        obj1[p] = obj2[p];
      }
    } catch(e) {
      // Property in destination object not set; create it and set its value.
      obj1[p] = obj2[p];
    }
  }
  return obj1;
}

@Algy 2010-02-26 19:13:58

For not-too-complicated objects you could use JSON:

var obj1 = { food: 'pizza', car: 'ford' }
var obj2 = { animal: 'dog', car: 'chevy'}
var objMerge;

objMerge = JSON.stringify(obj1) + JSON.stringify(obj2);

// {"food": "pizza","car":"ford"}{"animal":"dog","car":"chevy"}

objMerge = objMerge.replace(/\}\{/, ","); //  \_ replace with comma for valid JSON

objMerge = JSON.parse(objMerge); // { food: 'pizza', animal: 'dog', car: 'chevy'}
// Of same keys in both objects, the last object's value is retained_/

Mind you that in this example "}{" must not occur within a string!

@Quamis 2013-09-03 10:55:01

var so1 = JSON.stringify(obj1); var so2 = JSON.stringify(obj1); objMerge = so1.substr(0, so1.length-1)+","+so2.substr(1); console.info(objMerge);

@Alex Ivasyuv 2015-03-04 14:54:57

function merge(obj1, obj2) { return JSON.parse((JSON.stringify(obj1) + JSON.stringify(obj2)) .replace(/\}\{/g, ',').replace(/,\}/g, '}').replace(/\{,/g, '{')); }

@Rabbi Shuki Gur 2017-01-20 07:06:47

or as a one-liner: objMerge = JSON.parse((JSON.stringify(obj1) + JSON.stringify(obj2)).replace(/\}\{/, ", "));

@Bekim Bacaj 2017-04-15 15:49:15

@Charles, sorry but how is "this method very dangerous" but also fun - this is the safest possible 1stly it uses JSON to do the heavy lifting of reading the object contents, secondly, it uses JSON object which is by all means the safest machine optimized of reparsing JSO from a JSON compatible object string literal. And is also backward compatible with IE8 which is the first browser to implement its standard. It just makes me wonder "why oh why did you have to say such a stupid thing and get away with it"?

@yeahdixon 2018-03-25 04:23:41

I believe functions in the object will break down here since stringify cant be used, but can we clarify other downsides?

@ToolmakerSteve 2019-10-04 10:54:18

As a general rule, do not use solutions that rely on parsing, when there are known solutions that do not need parsing. In this case, requiring that "}{" not occur in a string seems "harmless enough" - but it could happen, so this isn't a great technique to rely on. And of course, it doesn't scale well (performance, memory), for deeply nested objects, given that you are converting to string and back. IMHO, Just don't do this.

@Eugene Tiurin 2015-12-15 16:59:21

Merge properties of N objects in one line of code

An Object.assign method is part of the ECMAScript 2015 (ES6) standard and does exactly what you need. (IE not supported)

var clone = Object.assign({}, obj);

The Object.assign() method is used to copy the values of all enumerable own properties from one or more source objects to a target object.

Read more...

The polyfill to support older browsers:

if (!Object.assign) {
  Object.defineProperty(Object, 'assign', {
    enumerable: false,
    configurable: true,
    writable: true,
    value: function(target) {
      'use strict';
      if (target === undefined || target === null) {
        throw new TypeError('Cannot convert first argument to object');
      }

      var to = Object(target);
      for (var i = 1; i < arguments.length; i++) {
        var nextSource = arguments[i];
        if (nextSource === undefined || nextSource === null) {
          continue;
        }
        nextSource = Object(nextSource);

        var keysArray = Object.keys(nextSource);
        for (var nextIndex = 0, len = keysArray.length; nextIndex < len; nextIndex++) {
          var nextKey = keysArray[nextIndex];
          var desc = Object.getOwnPropertyDescriptor(nextSource, nextKey);
          if (desc !== undefined && desc.enumerable) {
            to[nextKey] = nextSource[nextKey];
          }
        }
      }
      return to;
    }
  });
}

@Bekim Bacaj 2017-04-20 19:39:10

what does 'use strict' do in older browsersm or why is it there at all. browsers that support object[defineProperty; keys; getOwnPropertyDescriptor; etc], are not exactly old. They're just earlier versions of gen.5 UAs.

@Sridhar Sarnobat 2017-05-09 05:59:46

Thanks for clarifying that Objects.assign returns a merged object which the other answers don't. That's more functional programming style.

@toster-cx 2017-04-24 18:29:34

ES5 compatible native one-liner:

var merged = [obj1, obj2].reduce(function(a, o) { for(k in o) a[k] = o[k]; return a; }, {})

@Paul Spaulding 2013-04-23 20:45:20

Here's my stab which

  1. Supports deep merge
  2. Does not mutate arguments
  3. Takes any number of arguments
  4. Does not extend the object prototype
  5. Does not depend on another library (jQuery, MooTools, Underscore.js, etc.)
  6. Includes check for hasOwnProperty
  7. Is short :)

    /*
        Recursively merge properties and return new object
        obj1 &lt;- obj2 [ &lt;- ... ]
    */
    function merge () {
        var dst = {}
            ,src
            ,p
            ,args = [].splice.call(arguments, 0)
        ;
    
        while (args.length > 0) {
            src = args.splice(0, 1)[0];
            if (toString.call(src) == '[object Object]') {
                for (p in src) {
                    if (src.hasOwnProperty(p)) {
                        if (toString.call(src[p]) == '[object Object]') {
                            dst[p] = merge(dst[p] || {}, src[p]);
                        } else {
                            dst[p] = src[p];
                        }
                    }
                }
            }
        }
    
       return dst;
    }
    

Example:

a = {
    "p1": "p1a",
    "p2": [
        "a",
        "b",
        "c"
    ],
    "p3": true,
    "p5": null,
    "p6": {
        "p61": "p61a",
        "p62": "p62a",
        "p63": [
            "aa",
            "bb",
            "cc"
        ],
        "p64": {
            "p641": "p641a"
        }
    }
};

b = {
    "p1": "p1b",
    "p2": [
        "d",
        "e",
        "f"
    ],
    "p3": false,
    "p4": true,
    "p6": {
        "p61": "p61b",
        "p64": {
            "p642": "p642b"
        }
    }
};

c = {
    "p1": "p1c",
    "p3": null,
    "p6": {
        "p62": "p62c",
        "p64": {
            "p643": "p641c"
        }
    }
};

d = merge(a, b, c);


/*
    d = {
        "p1": "p1c",
        "p2": [
            "d",
            "e",
            "f"
        ],
        "p3": null,
        "p5": null,
        "p6": {
            "p61": "p61b",
            "p62": "p62c",
            "p63": [
                "aa",
                "bb",
                "cc"
            ],
            "p64": {
                "p641": "p641a",
                "p642": "p642b",
                "p643": "p641c"
            }
        },
        "p4": true
    };
*/

@Jasdeep Khalsa 2015-03-27 14:48:34

Compared to the others I tested from this page, this function is truly recursive (does a deep merge) and mimics what jQuery.extend() does really well. However, it would be better for it to modify the first object/argument so a user can decide if they want to pass in an empty object {} as the first parameter or have the function modify the original object. Therefore if you change dst = {} to dst = arguments[0] it will change the first object you pass in to the merged object

@m03geek 2015-05-21 14:51:18

Now it's stopped working in chrome. I think it's bad idea to use such construction toString.call(src) == '[object Object]' for checking if there's an object or not. typeof src is much better. Moreover it transforms Arrays into object (At leas I've got such behavior on latest chrome).

@Arnaud Bouchot 2016-10-11 14:13:51

I needed to do this inside a greedy loop, I've benchmarked this function VS the one I was using so far _.merge(object, [sources]) from lodash (a sort of underscore lib) : your function is almost twice faster thanks mate.

@mitch3ls 2017-02-02 12:15:00

You can do the following in EcmaScript2016

Correction: it's a stage 3 proposal, still it has always worked for me

const objA = {
  attrA: 'hello',
  attrB: true
}

const objB = {
  attrC: 2
}

const mergedObj = {...objA, ...objB}

@Michał Perłakowski 2017-02-02 13:09:30

Object spread properties are not a part of ES2016—it's a stage 3 proposal. Also, it was already covered in this answer.

@Jaime Asm 2017-01-27 09:55:11

You can use object spread properties—currently a stage 3 ECMAScript proposal.

const obj1 = { food: 'pizza', car: 'ford' };
const obj2 = { animal: 'dog' };

const obj3 = { ...obj1, ...obj2 };
console.log(obj3);

@Alph.Dev 2017-10-11 10:01:26

Browser support?

@connexo 2018-01-02 10:32:28

@Alph.Dev You do know caniuse.com?

@klewis 2018-03-16 19:52:49

I can't get the 3 dot syntax to work in node.js. node complains about it.

@trincot 2016-12-31 11:04:17

If you need a deep merge that will also "merge" arrays by concatenating them in the result, then this ES6 function might be what you need:

function deepMerge(a, b) {
    // If neither is an object, return one of them:
    if (Object(a) !== a && Object(b) !== b) return b || a;
    // Replace remaining primitive by empty object/array
    if (Object(a) !== a) a = Array.isArray(b) ? [] : {};
    if (Object(b) !== b) b = Array.isArray(a) ? [] : {};
    // Treat arrays differently:
    if (Array.isArray(a) && Array.isArray(b)) {
        // Merging arrays is interpreted as concatenation of their deep clones:
        return [...a.map(v => deepMerge(v)), ...b.map(v => deepMerge(v))];
    } else {
        // Get the keys that exist in either object
        var keys = new Set([...Object.keys(a),...Object.keys(b)]);
        // Recurse and assign to new object
        return Object.assign({}, ...Array.from(keys,
            key => ({ [key]: deepMerge(a[key], b[key]) }) ));
    }
}

// Sample data for demo:
var a = {
    groups: [{
        group: [{
            name: 'John',
            age: 12
        },{
            name: 'Mary',
            age: 20
        }],
        groupName: 'Pair'
    }],
    config: {
        color: 'blue',
        range: 'far'
    }
};


var b = {
    groups: [{
        group: [{
            name: 'Bill',
            age: 15
        }],
        groupName: 'Loner'
    }],
    config: {
        range: 'close',
        strength: 'average'
    }
};

var merged = deepMerge(a, b);

console.log(merged);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Note that if only one argument is passed to this function, it acts as a deep clone function.

@Nishant Kumar 2016-01-11 09:20:26

Here what I used in my codebase to merge.

function merge(to, from) {
  if (typeof to === 'object' && typeof from === 'object') {
    for (var pro in from) {
      if (from.hasOwnProperty(pro)) {
        to[pro] = from[pro];
      }
    }
  }
  else{
      throw "Merge function can apply only on object";
  }
}

@Vikash Pandey 2015-09-26 18:17:09

If you are using Dojo Toolkit then the best way to merge two object is using a mixin.

Below is the sample for Dojo Toolkit mixin:

// Dojo 1.7+ (AMD)
require(["dojo/_base/lang"], function(lang){
  var a = { b:"c", d:"e" };
  lang.mixin(a, { d:"f", g:"h" });
  console.log(a); // b:c, d:f, g:h
});

// Dojo < 1.7
var a = { b:"c", d:"e" };
dojo.mixin(a, { d:"f", g:"h" });
console.log(a); // b:c, d:f, g:h

For more details, please mixin.

@Etherealone 2015-04-21 21:18:27

I use the following which is in pure JavaScript. It starts from the right-most argument and combines them all the way up to the first argument. There is no return value, only the first argument is modified and the left-most parameter (except the first one) has the highest weight on properties.

var merge = function() {
  var il = arguments.length;

  for (var i = il - 1; i > 0; --i) {
    for (var key in arguments[i]) {
      if (arguments[i].hasOwnProperty(key)) {
        arguments[0][key] = arguments[i][key];
      }
    }
  }
};

@T.Todua 2015-03-31 17:09:41

Another method:

function concat_collection(obj1, obj2) {
    var i;
    var arr = new Array();

    var len1 = obj1.length;
    for (i=0; i<len1; i++) {
        arr.push(obj1[i]);
    }

    var len2 = obj2.length;
    for (i=0; i<len2; i++) {
        arr.push(obj2[i]);
    }

    return arr;
}

var ELEMENTS = concat_collection(A,B);
for(var i = 0; i < ELEMENTS.length; i++) {
    alert(ELEMENTS[i].value);
}

@appsmatics 2015-01-30 00:59:48

The following two are probably a good starting point. lodash also has a customizer function for those special needs!

_.extend (http://underscorejs.org/#extend)
_.merge (https://lodash.com/docs#merge)

@Wtower 2016-09-01 13:39:35

Please note that the above methods mutate the original object.

@SamBrick 2017-09-01 09:44:45

The lodash method worked for me as I wanted to merge two objects and retain properties nested more then one or two levels deep (rather than just replacing/wiping them).

@Martin Cremer 2019-10-10 10:09:24

true @Wtower. Just had a bug because of this. Best make sure it always starts like _.merge({}, ...

@antitoxic 2014-06-22 21:02:47

There's a library called deepmerge on GitHub: That seems to be getting some traction. It's a standalone, available through both the npm and bower package managers.

I would be inclined to use or improve on this instead of copy-pasting code from answers.

@Ryan Walls 2014-04-08 21:30:26

For those using Node.js, there's an NPM module: node.extend

Install:

npm install node.extend

Usage:

var extend = require('node.extend');
var destObject = extend(true, {}, sourceObject);
// Where sourceObject is the object whose properties will be copied into another.

@ItalyPaleAle 2014-04-29 20:34:56

This is not a builtin library, it's a NPM module.

@devmao 2014-03-15 10:54:56

With Underscore.js, to merge an array of objects do:

var arrayOfObjects = [ {a:1}, {b:2, c:3}, {d:4} ];
_(arrayOfObjects).reduce(function(memo, o) { return _(memo).extend(o); });

It results in:

Object {a: 1, b: 2, c: 3, d: 4}

@AndreasE 2014-01-27 21:00:57

Similar to jQuery extend(), you have the same function in AngularJS:

// Merge the 'options' object into the 'settings' object
var settings = {validate: false, limit: 5, name: "foo"};
var options  = {validate: true, name: "bar"};
angular.extend(settings, options);

@naXa 2016-03-13 13:29:37

@juanmf what for?

@juanmf 2016-03-22 13:10:55

@naXa I think it'd be an option if you don't want to add a lib just for this fn.

Related Questions

Sponsored Content

89 Answered Questions

[SOLVED] How do I remove a particular element from an array in JavaScript?

  • 2011-04-23 22:17:18
  • Walker
  • 6162770 View
  • 7685 Score
  • 89 Answer
  • Tags:   javascript arrays

86 Answered Questions

[SOLVED] How do JavaScript closures work?

65 Answered Questions

[SOLVED] How do I correctly clone a JavaScript object?

41 Answered Questions

[SOLVED] How do I remove a property from a JavaScript object?

38 Answered Questions

[SOLVED] Length of a JavaScript object

47 Answered Questions

[SOLVED] How to check if an object is an array?

58 Answered Questions

[SOLVED] How do I include a JavaScript file in another JavaScript file?

69 Answered Questions

[SOLVED] What is the most efficient way to deep clone an object in JavaScript?

47 Answered Questions

3 Answered Questions

Sponsored Content