Skip to content Skip to sidebar Skip to footer

Merge Js Objects Without Overwriting

Suppose you have two objects: var foo = { a : 1, b : 2 }; var bar = { a : 3, b : 4 } What's the best way to merge them (and allow deep merging) to create this: v

Solution 1:

This ought to do what you're looking for. It will recursively merge arbitrarily deep objects into arrays.

// deepmerge by Zachary Murray (dremelofdeath) CC-BY-SA 3.0function deepmerge(foo, bar) {
  var merged = {};
  for (var each in bar) {
    if (foo.hasOwnProperty(each) && bar.hasOwnProperty(each)) {
      if (typeof(foo[each]) == "object" && typeof(bar[each]) == "object") {
        merged[each] = deepmerge(foo[each], bar[each]);
      } else {
        merged[each] = [foo[each], bar[each]];
      }
    } elseif(bar.hasOwnProperty(each)) {
      merged[each] = bar[each];
    }
  }
  for (var each in foo) {
    if (!(each in bar) && foo.hasOwnProperty(each)) {
      merged[each] = foo[each];
    }
  }
  return merged;
}

And this one will do the same, except that the merged object will include copies of inherited properties. This probably isn't what you're looking for (as per RobG's comments below), but if that is actually what you are looking for, then here it is:

// deepmerge_inh by Zachary Murray (dremelofdeath) CC-BY-SA 3.0function deepmerge_inh(foo, bar) {
  var merged = {};
  for (var each in bar) {
    if (each in foo) {
      if (typeof(foo[each]) == "object" && typeof(bar[each]) == "object") {
        merged[each] = deepmerge(foo[each], bar[each]);
      } else {
        merged[each] = [foo[each], bar[each]];
      }
    } else {
      merged[each] = bar[each];
    }
  }
  for (var each in foo) {
    if (!(each in bar)) {
      merged[each] = foo[each];
    }
  }
  return merged;
}

I tried it out with your example on http://jsconsole.com, and it worked fine:

deepmerge(foo, bar)
{"a": [1, 3], "b": [2, 4]}
bar
{"a": 3, "b": 4}
foo
{"a": 1, "b": 2}

Slightly more complicated objects worked as well:

deepmerge(as, po)
{"a": ["asdf", "poui"], "b": 4, "c": {"q": [1, 444], "w": [function () {return5;}, function () {return1123;}]}, "o": {"b": {"t": "cats"}, "q": 7}, "p": 764}
po
{"a": "poui", "c": {"q": 444, "w": function () {return1123;}}, "o": {"b": {"t": "cats"}, "q": 7}, "p": 764}
as
{"a": "asdf", "b": 4, "c": {"q": 1, "w": function () {return5;}}}

Solution 2:

Presumably you would iterate over one object and copy its property names to a new object and values to arrays assigned to those properties. Iterate over subsequent objects, adding properties and arrays if they don't already exist or adding their values to existing properties and arrays.

e.g.

function mergeObjects(a, b,c){c=c||{};
  var p;

  for(p in a){if(a.hasOwnProperty(p)){if(c.hasOwnProperty(p)){c[p].push(a[p]);
      }else{c[p]=[a[p]];
      }}}for(p in b){if(b.hasOwnProperty(p)){if(c.hasOwnProperty(p)){c[p].push(b[p]);
      }else{c[p]=[b[p]];
      }}}returnc;
}

You could modify it to handle any number of objects by iterating over the arguments supplied, but that would make passing the object to merge into more difficult.

Solution 3:

https://lodash.com/docs/3.10.1#merge

// using a customizer callbackvar object = {
  'fruits': ['apple'],
  'vegetables': ['beet']
};

var other = {
  'fruits': ['banana'],
  'vegetables': ['carrot']
};

_.merge(object, other, function(a, b) {
  if (_.isArray(a)) {
    return a.concat(b);
  }
});
// → { 'fruits': ['apple', 'banana'], 'vegetables': ['beet', 'carrot'] }

Post a Comment for "Merge Js Objects Without Overwriting"