How can I merge properties of two JavaScript objects?
Asked Answered
A

69

3295

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

Is there 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.

Admonitory answered 5/10, 2008 at 0:31 Comment(2)
Its worth noting this answer on a similar question, which shows how to merge "one level down". That is, it merges values of duplicate keys (instead of overwriting first value with second value), but does not recurse further than that. IMHO, its good clean code for that task.Infrequent
BTW, the top few answers do a "shallow" merge: if the same key exists in both obj1 and obj2, the value in obj2 is kept, the value in obj1 is dropped. E.g. if question's example had var obj2 = { animal: 'dog', food: 'bone' };, the merge would be { food: 'bone', car: 'ford', animal: 'dog' }. If you are working with "nested data", and want a "deep merge", then look for answers that mention "deep merge" or "recursion". If you have values that are arrays, then use "arrayMerge" option of github "TehShrike/deepmerge", as mentioned here.Infrequent
M
4071

ECMAScript 2018 Standard Method

You would use object spread:

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

merged is now the union of obj1 and obj2. Properties in obj2 will overwrite those in obj1.

/** 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. If you're using babel you'll need the @babel/plugin-proposal-object-rest-spread plugin for it to work (This plugin is included in @babel/preset-env, in ES2018).

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;
}

additionally :- check this program for see differnce between Object.assign & spread syntax object literals

Matherly answered 5/10, 2008 at 0:31 Comment(6)
This doesn't work if objects have same name attributes, and you would also want to merge the attributes.Whitneywhitson
This only does a shallow copy/merge. Has the potential to clobber a lot of elements.Staley
​+1 for acknowledging that some poor souls are forced to use frameworks that crap all over their prototypes...Danika
Object.assign(obj1, obj2); may be the preferable way as let merged = {...obj1, ...obj2}; creates a new object and copies the the properties of obj1 and obj2 into it which may be very expensive for large objects. The assign method also modifies obj1 like the behavior expected in the question.Leftwards
for see diffrence between Object.assign & spread syntax object literals jsfiddle.net/fmcajhsv . i hope this one help to youShellishellie
How about if I need to concatenate certain key which is present in both object? Like on my example below, I want to concatenate the functions init_callback var defaultOptions= { init_callback: tce.tceActionEvent, name: "foo"}; var options = { init_callback: function(e) {}, name: "bar" };Maw
L
1243

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.
Lithosphere answered 5/10, 2008 at 0:31 Comment(2)
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);Repress
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.Piotr
S
393

The Harmony ECMAScript 2015 (ES6) specifies Object.assign which will do this.

Object.assign(obj1, obj2);

Current browser support is getting better, but if you're developing for browsers that don't have support, you can use a polyfill.

Syndesis answered 5/10, 2008 at 0:31 Comment(4)
Note that this is only a shallow mergeShaveling
I think meanwhile Object.assign has pretty decent coverage: kangax.github.io/compat-table/es6/…Upkeep
This should now be the correct answer. People nowadays compile their code to be compatible with the rare browser (IE11) that doesn't support this kind of thing. Side note: if you don't want to add obj2 to obj1, you can return a new object using Object.assign({}, obj1, obj2)Hepatitis
@Hepatitis According to reports I've seen, IE11 is definitely not rare at around 18% of the market share as of July 2016.Syndesis
P
300

I googled for code to merge object properties and ended up here. However since there wasn't any code for recursive merge I wrote it myself. (Maybe jQuery extend is recursive BTW?) Anyhow, hopefully someone else will find it useful as well.

(Now the code does not use Object.prototype :)

Code

/*
* Recursively merge properties of two objects 
*/
function MergeRecursive(obj1, 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 {
        obj1[p] = obj2[p];

      }

    } catch(e) {
      // Property in destination object not set; create it and set its value.
      obj1[p] = obj2[p];

    }
  }

  return obj1;
}

An example

o1 = {  a : 1,
        b : 2,
        c : {
          ca : 1,
          cb : 2,
          cc : {
            cca : 100,
            ccb : 200 } } };

o2 = {  a : 10,
        c : {
          ca : 10,
          cb : 20, 
          cc : {
            cca : 101,
            ccb : 202 } } };

o3 = MergeRecursive(o1, o2);

Produces object o3 like

o3 = {  a : 10,
        b : 2,
        c : {
          ca : 10,
          cb : 20,
          cc : { 
            cca : 101,
            ccb : 202 } } };
Pyrethrin answered 5/10, 2008 at 0:31 Comment(2)
Nice, but I would make a deepcopy of the objects first. This way o1 would be modified too, as objects are passed by reference.Twentieth
This code introduces a prototype pollution vulnerability: var data = {}; var json = '{"a": "1", "__proto__": { "x": "pwnd" }}'; MergeRecursive(data, JSON.parse(json)); var data2 = {}; console.log(data2.x);Willhite
T
182

Note that underscore.js's extend-method does this in a one-liner:

_.extend({name : 'moe'}, {age : 50});
=> {name : 'moe', age : 50}
Tetralogy answered 5/10, 2008 at 0:31 Comment(1)
This example is fine as you're dealing with anonymous objects, but if this is not the case then webmat's comment in the jQuery answer warning about mutations applies here, as underscore also mutates the destination object. Like the jQuery answer, to do this mutation-free just merge into an empty object: _({}).extend(obj1, obj2);Wight
E
86

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);
Edmiston answered 5/10, 2008 at 0:31 Comment(0)
L
68

I need to merge objects today, and this question (and answers) helped me a lot. I tried some of the answers, but none of them fit my needs, so I combined some of the answers, added something myself and came up with a new merge function. Here it is:

var merge = function() {
    var obj = {},
        i = 0,
        il = arguments.length,
        key;
    for (; i < il; i++) {
        for (key in arguments[i]) {
            if (arguments[i].hasOwnProperty(key)) {
                obj[key] = arguments[i][key];
            }
        }
    }
    return obj;
};

Some example usages:

var t1 = {
    key1: 1,
    key2: "test",
    key3: [5, 2, 76, 21]
};
var t2 = {
    key1: {
        ik1: "hello",
        ik2: "world",
        ik3: 3
    }
};
var t3 = {
    key2: 3,
    key3: {
        t1: 1,
        t2: 2,
        t3: {
            a1: 1,
            a2: 3,
            a4: [21, 3, 42, "asd"]
        }
    }
};

console.log(merge(t1, t2));
console.log(merge(t1, t3));
console.log(merge(t2, t3));
console.log(merge(t1, t2, t3));
console.log(merge({}, t1, { key1: 1 }));
Lubberly answered 5/10, 2008 at 0:31 Comment(0)
S
63

You can use the object spread syntax to achieve this. It's a part of ES2018 and beyond.

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

const obj3 = { ...obj1, ...obj2 };
console.log(obj3);
Scud answered 5/10, 2008 at 0:31 Comment(5)
Browser support?Mirador
@Alph.Dev You do know caniuse.com?Kisor
I can't get the 3 dot syntax to work in node.js. node complains about it.Ennead
What does ... (3 dot) represents?Ventage
It's call the Spread syntax and can be used when elements from an object or array need to be included in a new array or object. Pretty neat. Check this out - [developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…Chateau
F
42

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;
    }
  });
}
Fubsy answered 5/10, 2008 at 0:31 Comment(0)
A
42

The given solutions should be modified to check source.hasOwnProperty(property) in the for..in loops before assigning - otherwise, you end up copying the properties of the whole prototype chain, which is rarely desired...

Angry answered 5/10, 2008 at 0:31 Comment(0)
C
37

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)

Continuity answered 5/10, 2008 at 0:31 Comment(0)
M
34

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
    };
*/
Milburr answered 5/10, 2008 at 0:31 Comment(0)
H
33

Just by the way, what you're all doing is overwriting properties, not merging...

This is how JavaScript objects area really merged: Only keys in the to object which are not objects themselves will be overwritten by from. Everything else will be really merged. Of course you can change this behaviour to not overwrite anything which exists like only if to[n] is undefined, etc...:

var realMerge = function (to, from) {

    // Make sure to make a shallow copy first, otherwise
    // the original objects are mutated. 
    to = {...to};
    from = {...from};

    for (n in from) {

        if (typeof to[n] != 'object') {
            to[n] = from[n];
        } else if (typeof from[n] == 'object') {
            to[n] = realMerge(to[n], from[n]);
        }
    }
    return to;
};

Usage:

var merged = realMerge(obj1, obj2);
Homogenetic answered 5/10, 2008 at 0:31 Comment(0)
B
20

Object.assign()

ECMAScript 2015 (ES6)

This is a new technology, part of the ECMAScript 2015 (ES6) standard. This technology's specification has been finalized, but check the compatibility table for usage and implementation status in various browsers.

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. It will return the target object.

var o1 = { a: 1 };
var o2 = { b: 2 };
var o3 = { c: 3 };

var obj = Object.assign(o1, o2, o3);
console.log(obj); // { a: 1, b: 2, c: 3 }
console.log(o1);  // { a: 1, b: 2, c: 3 }, target object itself is changed.
Bulter answered 5/10, 2008 at 0:31 Comment(0)
Y
20

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!

Yarmouth answered 5/10, 2008 at 0:31 Comment(0)
T
17

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.

Torso answered 5/10, 2008 at 0:31 Comment(0)
B
16

The best way for you to do this is to add a proper property that is non-enumerable using Object.defineProperty.

This way you will still be able to iterate over your objects properties without having the newly created "extend" that you would get if you were to create the property with Object.prototype.extend.

Hopefully this helps:

Object.defineProperty(Object.prototype, "extend", {
    enumerable: false,
    value: function(from) {
        var props = Object.getOwnPropertyNames(from);
        var dest = this;
        props.forEach(function(name) {
            if (name in dest) {
                var destination = Object.getOwnPropertyDescriptor(from, name);
                Object.defineProperty(dest, name, destination);
            }
        });
        return this;
    }
});

Once you have that working, you can do:

var obj = {
    name: 'stack',
    finish: 'overflow'
}
var replacement = {
    name: 'stock'
};

obj.extend(replacement);

I just wrote a blog post about it here: http://onemoredigit.com/post/1527191998/extending-objects-in-node-js

Boniface answered 5/10, 2008 at 0:31 Comment(0)
H
15

You can simply use jQuery extend

var obj1 = { val1: false, limit: 5, name: "foo" };
var obj2 = { val2: true, name: "bar" };

jQuery.extend(obj1, obj2);

Now obj1 contains all the values of obj1 and obj2

Huelva answered 5/10, 2008 at 0:31 Comment(0)
F
15

Prototype has this:

Object.extend = function(destination,source) {
    for (var property in source)
        destination[property] = source[property];
    return destination;
}

obj1.extend(obj2) will do what you want.

Firebrick answered 5/10, 2008 at 0:31 Comment(0)
E
14

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


ES5 & Earlier

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++) {
        // Uncomment to skip arguments that are not objects (to prevent errors)
        // 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;
}

Example

/**
 * Extend objects
 */
function extend() {
    for (var o = {}, i = 0; i < arguments.length; i++) {
        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;
}

/**
 * Example
 */
document.write(JSON.stringify(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 ...

Ep answered 5/10, 2008 at 0:31 Comment(0)
D
13

Just if anyone is using Google Closure Library:

goog.require('goog.object');
var a = {'a': 1, 'b': 2};
var b = {'b': 3, 'c': 4};
goog.object.extend(a, b);
// Now object a == {'a': 1, 'b': 3, 'c': 4};

Similar helper function exists for array:

var a = [1, 2];
var b = [3, 4];
goog.array.extend(a, b); // Extends array 'a'
goog.array.concat(a, b); // Returns concatenation of array 'a' and 'b'
Discoverer answered 5/10, 2008 at 0:31 Comment(0)
C
12

**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

Custodial answered 5/10, 2008 at 0:31 Comment(0)
W
11
var firstObject = {
    key1 : 'value1',
    key2 : 'value2'
};

var secondObject={
  ...firstObject,
  key3 : 'value3',
  key4 : 'value4',
  key5 : 'value5'
}
console.log(firstObject);
console.log(secondObject);
Wordy answered 5/10, 2008 at 0:31 Comment(0)
N
11

I extended David Coallier's method:

  • Added the possibility to merge multiple objects
  • Supports deep objects
  • override parameter (that's detected if the last parameter is a boolean)

If override is false, no property gets overridden but new properties will be added.

Usage: obj.merge(merges... [, override]);

Here is my code:

Object.defineProperty(Object.prototype, "merge", {
    enumerable: false,
    value: function () {
        var override = true,
            dest = this,
            len = arguments.length,
            props, merge, i, from;

        if (typeof(arguments[arguments.length - 1]) === "boolean") {
            override = arguments[arguments.length - 1];
            len = arguments.length - 1;
        }

        for (i = 0; i < len; i++) {
            from = arguments[i];
            if (from != null) {
                Object.getOwnPropertyNames(from).forEach(function (name) {
                    var descriptor;

                    // nesting
                    if ((typeof(dest[name]) === "object" || typeof(dest[name]) === "undefined")
                            && typeof(from[name]) === "object") {

                        // ensure proper types (Array rsp Object)
                        if (typeof(dest[name]) === "undefined") {
                            dest[name] = Array.isArray(from[name]) ? [] : {};
                        }
                        if (override) {
                            if (!Array.isArray(dest[name]) && Array.isArray(from[name])) {
                                dest[name] = [];
                            }
                            else if (Array.isArray(dest[name]) && !Array.isArray(from[name])) {
                                dest[name] = {};
                            }
                        }
                        dest[name].merge(from[name], override);
                    } 

                    // flat properties
                    else if ((name in dest && override) || !(name in dest)) {
                        descriptor = Object.getOwnPropertyDescriptor(from, name);
                        if (descriptor.configurable) {
                            Object.defineProperty(dest, name, descriptor);
                        }
                    }
                });
            }
        }
        return this;
    }
});

Examples and TestCases:

function clone (obj) {
    return JSON.parse(JSON.stringify(obj));
}
var obj = {
    name : "trick",
    value : "value"
};

var mergeObj = {
    name : "truck",
    value2 : "value2"
};

var mergeObj2 = {
    name : "track",
    value : "mergeObj2",
    value2 : "value2-mergeObj2",
    value3 : "value3"
};

assertTrue("Standard", clone(obj).merge(mergeObj).equals({
    name : "truck",
    value : "value",
    value2 : "value2"
}));

assertTrue("Standard no Override", clone(obj).merge(mergeObj, false).equals({
    name : "trick",
    value : "value",
    value2 : "value2"
}));

assertTrue("Multiple", clone(obj).merge(mergeObj, mergeObj2).equals({
    name : "track",
    value : "mergeObj2",
    value2 : "value2-mergeObj2",
    value3 : "value3"
}));

assertTrue("Multiple no Override", clone(obj).merge(mergeObj, mergeObj2, false).equals({
    name : "trick",
    value : "value",
    value2 : "value2",
    value3 : "value3"
}));

var deep = {
    first : {
        name : "trick",
        val : "value"
    },
    second : {
        foo : "bar"
    }
};

var deepMerge = {
    first : {
        name : "track",
        anotherVal : "wohoo"
    },
    second : {
        foo : "baz",
        bar : "bam"
    },
    v : "on first layer"
};

assertTrue("Deep merges", clone(deep).merge(deepMerge).equals({
    first : {
        name : "track",
        val : "value",
        anotherVal : "wohoo"
    },
    second : {
        foo : "baz",
        bar : "bam"
    },
    v : "on first layer"
}));

assertTrue("Deep merges no override", clone(deep).merge(deepMerge, false).equals({
    first : {
        name : "trick",
        val : "value",
        anotherVal : "wohoo"
    },
    second : {
        foo : "bar",
        bar : "bam"
    },
    v : "on first layer"
}));

var obj1 = {a: 1, b: "hello"};
obj1.merge({c: 3});
assertTrue(obj1.equals({a: 1, b: "hello", c: 3}));

obj1.merge({a: 2, b: "mom", d: "new property"}, false);
assertTrue(obj1.equals({a: 1, b: "hello", c: 3, d: "new property"}));

var obj2 = {};
obj2.merge({a: 1}, {b: 2}, {a: 3});
assertTrue(obj2.equals({a: 3, b: 2}));

var a = [];
var b = [1, [2, 3], 4];
a.merge(b);
assertEquals(1, a[0]);
assertEquals([2, 3], a[1]);
assertEquals(4, a[2]);


var o1 = {};
var o2 = {a: 1, b: {c: 2}};
var o3 = {d: 3};
o1.merge(o2, o3);
assertTrue(o1.equals({a: 1, b: {c: 2}, d: 3}));
o1.b.c = 99;
assertTrue(o2.equals({a: 1, b: {c: 2}}));

// checking types with arrays and objects
var bo;
a = [];
bo = [1, {0:2, 1:3}, 4];
b = [1, [2, 3], 4];

a.merge(b);
assertTrue("Array stays Array?", Array.isArray(a[1]));

a = [];
a.merge(bo);
assertTrue("Object stays Object?", !Array.isArray(a[1]));

a = [];
a.merge(b);
a.merge(bo);
assertTrue("Object overrides Array", !Array.isArray(a[1]));

a = [];
a.merge(b);
a.merge(bo, false);
assertTrue("Object does not override Array", Array.isArray(a[1]));

a = [];
a.merge(bo);
a.merge(b);
assertTrue("Array overrides Object", Array.isArray(a[1]));

a = [];
a.merge(bo);
a.merge(b, false);
assertTrue("Array does not override Object", !Array.isArray(a[1]));

My equals method can be found here: Object comparison in JavaScript

Niveous answered 5/10, 2008 at 0:31 Comment(0)
W
9

In MooTools, there's Object.merge():

Object.merge(obj1, obj2);
Workday answered 5/10, 2008 at 0:31 Comment(0)
B
8
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"}
Belgravia answered 5/10, 2008 at 0:31 Comment(1)
The result4 can also be written without the {} var result4 = Object.assign(obj1,obj2);Ivette
L
8

In Ext JS 4 it can be done as follows:

var mergedObject = Ext.Object.merge(object1, object2)

// Or shorter:
var mergedObject2 = Ext.merge(object1, object2)

See merge( object ) : Object.

Laticialaticiferous answered 5/10, 2008 at 0:31 Comment(0)
B
7

It seems like this should be all you need:

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

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

After that obj3 should now have the following value:

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

Try it out here:

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

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

console.log(obj3);
Boride answered 5/10, 2008 at 0:31 Comment(0)
J
7

let obj1 = {a:1, b:2};
let obj2 = {c:3, d:4};
let merged = {...obj1, ...obj2};
console.log(merged);
Janettajanette answered 5/10, 2008 at 0:31 Comment(0)
P
7

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;
}
Proserpina answered 5/10, 2008 at 0:31 Comment(0)
T
6

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}
Tank answered 5/10, 2008 at 0:31 Comment(0)
K
5

You should use lodash's defaultsDeep

_.defaultsDeep({ 'user': { 'name': 'barney' } }, { 'user': { 'name': 'fred', 'age': 36 } });
// → { 'user': { 'name': 'barney', 'age': 36 } }
Kirov answered 5/10, 2008 at 0:31 Comment(0)
A
5

It's worth mentioning that the version from the 140byt.es collection is solving the task within minimum space and is worth a try for this purpose:

Code:

function m(a,b,c){for(c in b)b.hasOwnProperty(c)&&((typeof a[c])[0]=='o'?m(a[c],b[c]):a[c]=b[c])}

Usage for your purpose:

m(obj1,obj2);

Here's the original Gist.

Annora answered 5/10, 2008 at 0:31 Comment(0)
G
4

Use Spread operator which follows the ES6 version

var obj1 = { food: 'pizza', car: 'ford' }
var obj2 = { animal: 'dog' }
let result = {...obj1,...obj2};
console.log(result)

output { food: 'pizza', car: 'ford', animal: 'dog' }
Geotaxis answered 5/10, 2008 at 0:31 Comment(0)
P
4

You can use Object.assign method. For example:

var result = Object.assign(obj1, obj2);

Also, note that it creates a shallow copy of the object.

Pilsen answered 5/10, 2008 at 0:31 Comment(0)
A
4

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
  })
}
Alcoholize answered 5/10, 2008 at 0:31 Comment(1)
This does not seem to work? typescript-play.js.org/#code/…Aquiline
J
2

Use this

var t=merge({test:123},{mysecondTest:{blub:{test2:'string'},args:{'test':2}}})
console.log(t);

function merge(...args) {
  return Object.assign({}, ...args);
}
Jampan answered 5/10, 2008 at 0:31 Comment(0)
S
2
Object.assign(TargetObject, Obj1, Obj2, ...);
Sg answered 5/10, 2008 at 0:31 Comment(0)
T
2

There are different ways to achieve this:

Object.assign(targetObj, sourceObj);

targetObj = {...targetObj, ...sourceObj};
Thorma answered 5/10, 2008 at 0:31 Comment(0)
B
2

shallow

var obj = { name : "Jacob" , address : ["America"] }
var obj2 = { name : "Shaun" , address : ["Honk Kong"] }

var merged = Object.assign({} , obj,obj2 ); //shallow merge 
obj2.address[0] = "new city"

result.address[0] is changed to "new city" , i.e merged object is also changed. This is the problem with shallow merge.

deep

var obj = { name : "Jacob" , address : ["America"] }
var obj2 = { name : "Shaun" , address : ["Honk Kong"] }

var result = Object.assign({} , JSON.parse(JSON.stringify(obj)),JSON.parse(JSON.stringify(obj2)) )

obj2.address[0] = "new city"

result.address[0] is not changed

Beltz answered 5/10, 2008 at 0:31 Comment(1)
var merged = Object.assign({} , obj,obj2 ) does not merge anything?Air
D
2

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);
Dissuade answered 5/10, 2008 at 0:31 Comment(0)
G
2

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.

Granduncle answered 5/10, 2008 at 0:31 Comment(0)
E
2

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 ) )
;
Exhibition answered 5/10, 2008 at 0:31 Comment(0)
K
2

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];
      }
    }
  }
};
Killen answered 5/10, 2008 at 0:31 Comment(0)
S
2

My way:

function mergeObjects(defaults, settings) {
    Object.keys(defaults).forEach(function(key_default) {
        if (typeof settings[key_default] == "undefined") {
            settings[key_default] = defaults[key_default];
        } else if (isObject(defaults[key_default]) && isObject(settings[key_default])) {
            mergeObjects(defaults[key_default], settings[key_default]);
        }
    });

    function isObject(object) {
        return Object.prototype.toString.call(object) === '[object Object]';
    }

    return settings;
}

:)

Snowbird answered 5/10, 2008 at 0:31 Comment(0)
U
2

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 )
Unarm answered 5/10, 2008 at 0:31 Comment(6)
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!Matos
no it doesn't fail, I've just tried what you've said with success.Unarm
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.Atlantic
@Atlantic - 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 questionUnarm
@Unarm 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 :-)Atlantic
@Atlantic - 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 pageUnarm
S
2

gossi's extension of David Coallier's method:

Check these two lines:

from = arguments[i];
Object.getOwnPropertyNames(from).forEach(function (name) {

One need to check "from" against null object... If for example merging an object that comes from an Ajax response, previously created on a server, an object property can have a value of "null", and in that case the above code generates an error saying:

"from" is not a valid object

So for example, wrapping the "...Object.getOwnPropertyNames(from).forEach..." function with an "if (from != null) { ... }" will prevent that error occurring.

Surfboarding answered 5/10, 2008 at 0:31 Comment(0)
F
2

Use:

//Takes any number of objects and returns one merged object
var objectMerge = function(){
    var out = {};
    if(!arguments.length)
        return out;
    for(var i=0; i<arguments.length; i++) {
        for(var key in arguments[i]){
            out[key] = arguments[i][key];
        }
    }
    return out;
}

It was tested with:

console.log(objectMerge({a:1, b:2}, {a:2, c:4}));

It results in:

{ a: 2, b: 2, c: 4 }
Fixate answered 5/10, 2008 at 0:31 Comment(0)
B
1

Three ways you can do that:-

Approach 1:-

// using spread ...
    let obj1 = {
        ...obj2
    };

Approach2:-

// using  Object.assign() method
let obj1 = Object.assign({}, obj2);

Approach3:-

// using JSON
let obj1 = JSON.parse(JSON.stringify(obj2));
Bowknot answered 5/10, 2008 at 0:31 Comment(1)
The question was how to merge two objects, this answer is just copying an object.Musicale
G
1

ES5 compatible native one-liner:

var merged = [obj1, obj2].reduce(function(a, o) { for(k in o) a[k] = o[k]; return a; }, {})
General answered 5/10, 2008 at 0:31 Comment(0)
P
1

You can merge objects through following my method

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

var result = mergeObjects([obj1, obj2]);

console.log(result);
document.write("result: <pre>" + JSON.stringify(result, 0, 3) + "</pre>");

function mergeObjects(objectArray) {
    if (objectArray.length) {
        var b = "", i = -1;
        while (objectArray[++i]) {
            var str = JSON.stringify(objectArray[i]);
            b += str.slice(1, str.length - 1);
            if (objectArray[i + 1]) b += ",";
        }
        return JSON.parse("{" + b + "}");
    }
    return {};
}
Proulx answered 5/10, 2008 at 0:31 Comment(0)
C
1

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.
Cleanthes answered 5/10, 2008 at 0:31 Comment(1)
This is not a builtin library, it's a NPM module.Illsorted
F
1

I've used Object.create() to keep the default settings (utilising __proto__ or Object.getPrototypeOf() ).

function myPlugin( settings ){
    var defaults = {
        "keyName": [ "string 1", "string 2" ]
    }
    var options = Object.create( defaults );
    for (var key in settings) { options[key] = settings[key]; }
}
myPlugin( { "keyName": ["string 3", "string 4" ] } );

This way I can always 'concat()' or 'push()' later.

var newArray = options['keyName'].concat( options.__proto__['keyName'] );

Note: You'll need to do a hasOwnProperty check before concatenation to avoid duplication.

Fadge answered 5/10, 2008 at 0:31 Comment(0)
I
1

In YUI Y.merge should get the job done:

Y.merge(obj1, obj2, obj3....) 
Infarct answered 5/10, 2008 at 0:31 Comment(0)
N
1

I'm kind of getting started with JavaScript, so correct me if I'm wrong.

But wouldn't it be better if you could merge any number of objects? Here's how I do it using the native Arguments object.

The key to is that you can actually pass any number of arguments to a JavaScript function without defining them in the function declaration. You just can't access them without using the Arguments object.

function mergeObjects() (
    var tmpObj = {};

    for(var o in arguments) {
        for(var m in arguments[o]) {
            tmpObj[m] = arguments[o][m];
        }
    }
    return tmpObj;
}
Nonsectarian answered 5/10, 2008 at 0:31 Comment(0)
P
0

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)
Peafowl answered 5/10, 2008 at 0:31 Comment(0)
C
0

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";
  }
}
Cithara answered 5/10, 2008 at 0:31 Comment(0)
S
0

A possible way to achieve this is the following.

if (!Object.prototype.merge){
    Object.prototype.merge = function(obj){
        var self = this;
        Object.keys(obj).forEach(function(key){
            self[key] = obj[key]
        });
    }
};

I don't know if it's better then the other answers. In this method you add the merge function to Objects prototype. This way you can call obj1.merge(obj2);

Note : you should validate your argument to see if its an object and 'throw' a proper Error. If not Object.keys will 'throw' an 'Error'

Screwy answered 5/10, 2008 at 0:31 Comment(0)
E
0

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.

Evacuee answered 5/10, 2008 at 0:31 Comment(0)
M
0

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);
}
Marquet answered 5/10, 2008 at 0:31 Comment(0)
D
0

This solution creates a new object and is able to handle multiple objects.

Furthermore, it is recursive and you can chose weather you want to overwrite Values and Objects.

    function extendObjects() {

        var newObject        = {};
        var overwriteValues  = false;
        var overwriteObjects = false;

        for ( var indexArgument = 0; indexArgument < arguments.length; indexArgument++ ) {

            if ( typeof arguments[indexArgument] !== 'object' ) {

                if ( arguments[indexArgument] == 'overwriteValues_True' ) {

                    overwriteValues = true;            
                } else if ( arguments[indexArgument] == 'overwriteValues_False' ) {

                    overwriteValues = false;                             
                } else if ( arguments[indexArgument] == 'overwriteObjects_True' ) {

                    overwriteObjects = true;     
                } else if ( arguments[indexArgument] == 'overwriteObjects_False' ) {

                    overwriteObjects = false; 
                }

            } else {

                extendObject( arguments[indexArgument], newObject, overwriteValues, overwriteObjects );
            }

        }

        function extendObject( object, extendedObject, overwriteValues, overwriteObjects ) {

            for ( var indexObject in object ) {

                if ( typeof object[indexObject] === 'object' ) {

                    if ( typeof extendedObject[indexObject] === "undefined" || overwriteObjects ) {
                        extendedObject[indexObject] = object[indexObject];
                    }

                    extendObject( object[indexObject], extendedObject[indexObject], overwriteValues, overwriteObjects );

                } else {

                    if ( typeof extendedObject[indexObject] === "undefined" || overwriteValues ) {
                        extendedObject[indexObject] = object[indexObject];
                    }

                }

            }     

            return extendedObject;

        }

        return newObject;
    }

    var object1           = { a : 1, b : 2, testArr : [888, { innArr : 1 }, 777 ], data : { e : 12, c : { lol : 1 }, rofl : { O : 3 } } };
    var object2           = { a : 6, b : 9, data : { a : 17, b : 18, e : 13, rofl : { O : 99, copter : { mao : 1 } } }, hexa : { tetra : 66 } };
    var object3           = { f : 13, g : 666, a : 333, data : { c : { xD : 45 } }, testArr : [888, { innArr : 3 }, 555 ]  };

    var newExtendedObject = extendObjects( 'overwriteValues_False', 'overwriteObjects_False', object1, object2, object3 );

Contents of newExtendedObject:

{"a":1,"b":2,"testArr":[888,{"innArr":1},777],"data":{"e":12,"c":{"lol":1,"xD":45},"rofl":{"O":3,"copter":{"mao":1}},"a":17,"b":18},"hexa":{"tetra":66},"f":13,"g":666}

Fiddle: http://jsfiddle.net/o0gb2umb/

Dike answered 5/10, 2008 at 0:31 Comment(0)
C
0

You could assign every object a default merge (perhaps 'inherit' a better name) method:

It should work with either objects or instantiated functions.

The below code handles overriding the merged values if so desired:

Object.prototype.merge = function(obj, override) {
// Don't override by default

    for (var key in obj) {
        var n = obj[key];
        var t = this[key];
        this[key] = (override && t) ? n : t;
    };

};

Test data is below:

var Mammal = function () {
    this.eyes = 2;
    this.thinking_brain = false;
    this.say = function () {
    console.log('screaming like a mammal')};
}

var Human = function () {
    this.thinking_brain = true;
    this.say = function() {console.log('shouting like a human')};
}

john = new Human();

// Extend mammal, but do not override from mammal
john.merge(new Mammal());
john.say();

// Extend mammal and override from mammal
john.merge(new Mammal(), true);
john.say();
Conceptualize answered 5/10, 2008 at 0:31 Comment(0)
N
0
A={a:1,b:function(){alert(9)}}
B={a:2,c:3}
A.merge = function(){for(var i in B){A[i]=B[i]}}
A.merge()

Result is: {a:2,c:3,b:function()}

Neurasthenic answered 5/10, 2008 at 0:31 Comment(1)
btw, dojo has a function called mixin so, dojo.mixin(A,B) will do the trickNeurasthenic
D
0

This merges obj into a "default" def. obj has precedence for anything that exists in both, since obj is copied into def. Note also that this is recursive.

function mergeObjs(def, obj) {
    if (typeof obj == 'undefined') {
        return def;
    } else if (typeof def == 'undefined') {
        return obj;
    }
    for (var i in obj) {
        if (obj[i] != null && obj[i].constructor == Object) {
            def[i] = mergeObjs(def[i], obj[i]);
        } else {
            def[i] = obj[i];
        }
    }
    return def;
}

a = {x : {y : [123]}}
b = {x : {z : 123}}
console.log(mergeObjs(a, b));
// {x: {y : [123], z : 123}}
Domett answered 5/10, 2008 at 0:31 Comment(0)
E
0

The correct implementation in Prototype should look like this:

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

obj1 = Object.extend(obj1, obj2);
Exhaustless answered 5/10, 2008 at 0:31 Comment(0)
C
-1
function extend()
{ 
    var o = {}; 

    for (var i in arguments)
    { 
        var s = arguments[i]; 

        for (var i in s)
        { 
            o[i] = s[i]; 
        } 
    } 

    return o;
}
Carola answered 5/10, 2008 at 0:31 Comment(0)
D
-2

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}
Disposal answered 5/10, 2008 at 0:31 Comment(1)
Object spread properties are not a part of ES2016—it's a stage 3 proposal. Also, it was already covered in this answer.Behm
D
-2

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.

Dynah answered 5/10, 2008 at 0:31 Comment(0)
N
-3

Try this way using jQuery library

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

console.log(jQuery.extend(obj1, obj2))
Napiform answered 5/10, 2008 at 0:31 Comment(1)
This is just a repeat of this existing answer and this existing answer and this existing answer.Woodward

© 2022 - 2024 — McMap. All rights reserved.