Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Merge two objects without override

I have a defaultObject like that:

var default = {
    abc: "123",
    def: "456",
    ghi: {
       jkl: "789",
       mno: "012"
    }
};

And I have another like:

var values = {
    abc: "zzz",
    ghi: {
       jkl: "yyy",
    }
};

How can I merge those 2 objects with the following result (no override)?

var values = {
    abc: "zzz",
    def: "456",
    ghi: {
       jkl: "yyy",
       mno: "012"
    }
};

(I don't want to change the default object!)

like image 559
amp Avatar asked Dec 15 '13 01:12

amp


People also ask

How do you combine two objects?

To merge objects into a new one that has all properties of the merged objects, you have two options: Use a spread operator ( ... ) Use the Object. assign() method.

How do you concatenate objects in JavaScript?

The easiest way to merge two objects in JavaScript is with the ES6 spread syntax / operator ( ... ). All you have to do is insert one object into another object along with the spread syntax and any object you use the spread syntax on will be merged into the parent object.

How do I merge two objects in Lodash?

Lodash helps in working with arrays, strings, objects, numbers, etc. The _. merge() method is used to merge two or more objects starting with the left-most to the right-most to create a parent mapping object. When two keys are the same, the generated object will have value for the rightmost key.


2 Answers

For those who don't use jQuery, here comes a vanilla-js solution.

Solution:

function extend (target) {
    for(var i=1; i<arguments.length; ++i) {
        var from = arguments[i];
        if(typeof from !== 'object') continue;
        for(var j in from) {
            if(from.hasOwnProperty(j)) {
                target[j] = typeof from[j]==='object'
                ? extend({}, target[j], from[j])
                : from[j];
            }
        }
    }
    return target;
}

Compressed (with Closure Compiler):

Only 199 characters!

var extend=function e(c){for(var d=1;d<arguments.length;++d){var a=arguments[d];if("object"===typeof a)for(var b in a)a.hasOwnProperty(b)&&(c[b]="object"===typeof a[b]?e({},c[b],a[b]):a[b])}return c}

How to use:

extend(target, obj1, obj2); // returns target

If you only want to merge, use

var merged = extend({}, obj1, obj2);

Features:

  • It doesn't look at objects' prototype.
  • Ignores non-objects.
  • It is recursive in order to merge properties which are objects.
  • Objects referenced in target's properties, if extended, are replaced by new ones, and the original ones are not modified.
  • In case of same property names, the merged value will be the merging of the objects after the last (in the order of arguments) non-object value. Or, if the last isn't an object, itself.

Examples:

extend({}, {a:1}, {a:2});            // {a:2}
extend({}, {a:1}, {b:2});            // {a:1, b:2}
extend({}, {a: {b:1}}, {a: {b:2}});  // {a: {b:2}}
extend({}, {a: {b:1}}, {a: {c:2}});  // {a: {b:2, c:2}}
extend({}, {a: {a:1}}, {a: {b:2}}, {a: 'whatever non object'});
    // {a: "whatever non object"}
extend({}, {a: {a:1}}, {a: {b:2}}, {a: 'whatever non object'}, {a: {c:3}},{a: {d:4}});
    // {a: {c:3, d:4}}

Warning:

Be aware that if browser is not clever enough, it could be trapped in an infinite loop:

var obj1={},
    obj2={};
obj1.me=obj1;
obj2.me=obj2;
extend({},obj1,obj2);

If the browser is clever enough, it can throw an error, or return {me: undefined}, or whatever.

Note that this warning also applies if you use jQuery's $.extend.

like image 113
Oriol Avatar answered Oct 27 '22 21:10

Oriol


With ES2015 now being supported in all modern browsers, the native Object.assign can be used to extend objects

Object.assign({}, _default, values)

Object.assign

Note that default is a reserved keyword, and can't be used as a variable name


The original answer, written in 2013 :

Since this is tagged with jQuery, you could use $.extend for a simple cross-browser solution

var temp = {};
$.extend(true, temp, _default, values);
values = temp;

like image 30
adeneo Avatar answered Oct 27 '22 19:10

adeneo