我需要能够在运行时合并两个(非常简单)JavaScript对象。例如,我想:

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

obj1.merge(obj2);

//obj1 now has three properties: food, car, and animal

是否有一种内置的方法来实现这一点?我不需要递归,也不需要合并函数,只需要平面对象上的方法。


当前回答

值得一提的是,140byt.es集合的版本在最小空间内解决了这一任务,值得一试:

代码:

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

用途:

m(obj1,obj2);

这是原始的Gist。

其他回答

这是我的刺

支持深度合并不改变参数采用任意数量的参数不扩展对象原型不依赖于其他库(jQuery、MooTools、Undercore.js等)包括检查hasOwnProperty短:)/*递归合并财产并返回新对象对象1<-对象2[<-…]*/函数合并(){变量dst={},srcp,args=[].splice.call(参数,0);while(参数长度>0){src=参数拼接(0,1)[0];if(toString.call(src)=='[object object]'){for(src中的p){if(src.hasOwnProperty(p)){if(toString.call(src[p])=='[object object]'){dst[p]=合并(dst[p]||{},src[p]);}其他{dst[p]=src[p];}}}}}返回dst;}

例子:

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

gossi对David Coallier方法的扩展:

检查这两行:

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

需要针对空对象检查“from”。。。例如,如果合并以前在服务器上创建的来自Ajax响应的对象,则对象属性的值可以为“null”,在这种情况下,上述代码会生成一个错误消息:

“from”不是有效对象

因此,例如,将“…Object.getOwnPropertyNames(from).forEach…”函数包装为“if(from!=null){…}”将防止发生该错误。

我在谷歌上搜索了合并对象财产的代码,结果出现在这里。然而,由于没有递归合并的代码,我自己编写了它。(也许jQuery扩展是递归的BTW?)无论如何,希望其他人也会发现它很有用。

(现在代码不使用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;
}

一个例子

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

生成类似o3的对象

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

浅的

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.地址[0]更改为“新城”,即合并对象也更改。这就是浅层合并的问题。

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]未更改

原型中的正确实现应该如下所示:

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

obj1 = Object.extend(obj1, obj2);