Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
menu search
person
Welcome To Ask or Share your Answers For Others

Categories

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!)

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
253 views
Welcome To Ask or Share your Answers For Others

1 Answer

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.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
...