合并两个对象而不覆盖

我有一个像这样的defaultObject:

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

我有另一个喜欢:

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

如何将这两个对象与以下结果合并(无覆盖)?

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

(我不想更改默认对象!)

您可以使用$ .extend

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

请注意, default是保留关键字,不能用作变量名

如果您对ES6感到满意:

 Object.assign({}, default, values) 

对于那些不使用jQuery的人来说,这里有一个vanilla-js解决方案。

方案

 function extend (target) { for(var i=1; i 

压缩 (使用Closure Compiler ):

只有199个字符!

 var extend=function e(c){for(var d=1;d 

使用方法

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

如果您只想合并,请使用

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

特点

  • 它没有看对象的原型。
  • 忽略非对象。
  • 它是递归的,以便合并作为对象的属性。
  • target属性中引用的target (如果已扩展)将替换为新对象,并且不会修改原始对象。
  • 如果属性名称相同,则合并后的值将是最后一个(按参数顺序)非对象值之后的对象合并。 或者,如果最后一个不是对象本身。

示例

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

警告

请注意,如果浏览器不够聪明,它可能会陷入无限循环:

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

如果浏览器足够聪明,它可能会抛出错误,或者返回{me: undefined} ,或者其他什么。

请注意,如果您使用jQuery的$.extend ,此警告也适用。

另一种方法是默认情况下简单地扩展值(而不是覆盖默认值的另一种方式)

 Object.assign(value, default) // values of default overrides value default = value // reset default to value 

这里需要注意的是,价值的内容也会发生变化。 上面没有库是必需的,比上面的普通香草解决方案更容易。