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

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

obj1.merge(obj2);

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

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


当前回答

这似乎就是你所需要的:

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

var obj3 = { ...obj1, ...obj2 }

之后,obj3现在应该具有以下值:

{food: "pizza", car: "ford", animal: "dog"}

在这里试试:

var obj1={food:“pizza”,car:“ford”}var obj2={动物:“狗”}var obj3={…obj1,…obj2}console.log(obj3);

其他回答

在MooTools中,有Object.merge():

Object.merge(obj1, obj2);

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

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

obj1 = Object.extend(obj1, obj2);

基于Markus和vsync的回答,这是一个扩展版本。该函数接受任意数量的参数。它可以用于设置DOM节点上的财产,并对值进行深度复制。然而,第一个论点是通过引用给出的。

要检测DOM节点,使用isDOMNode()函数(请参阅堆栈溢出问题JavaScript isDOM-如何检查JavaScript对象是否为DOM对象?)

它在Opera 11、Firefox 6、Internet Explorer 8和Google Chrome 16中进行了测试。

Code

function mergeRecursive() {

  // _mergeRecursive does the actual job with two arguments.
  var _mergeRecursive = function (dst, src) {
    if (isDOMNode(src) || typeof src !== 'object' || src === null) {
      return dst;
    }

    for (var p in src) {
      if (!src.hasOwnProperty(p))
        continue;
      if (src[p] === undefined)
        continue;
      if ( typeof src[p] !== 'object' || src[p] === null) {
        dst[p] = src[p];
      } else if (typeof dst[p]!=='object' || dst[p] === null) {
        dst[p] = _mergeRecursive(src[p].constructor===Array ? [] : {}, src[p]);
      } else {
        _mergeRecursive(dst[p], src[p]);
      }
    }
    return dst;
  }

  // Loop through arguments and merge them into the first argument.
  var out = arguments[0];
  if (typeof out !== 'object' || out === null)
    return out;
  for (var i = 1, il = arguments.length; i < il; i++) {
    _mergeRecursive(out, arguments[i]);
  }
  return out;
}

一些示例

设置HTML元素的innerHTML和样式

mergeRecursive(
  document.getElementById('mydiv'),
  {style: {border: '5px solid green', color: 'red'}},
  {innerHTML: 'Hello world!'});

合并数组和对象。请注意,undefined可用于保存左侧数组/对象中的值。

o = mergeRecursive({a:'a'}, [1,2,3], [undefined, null, [30,31]], {a:undefined, b:'b'});
// o = {0:1, 1:null, 2:[30,31], a:'a', b:'b'}

任何非JavaScript对象的参数(包括null)都将被忽略。除了第一个参数之外,也会丢弃DOM节点。注意,像new String()这样创建的字符串实际上是对象。

o = mergeRecursive({a:'a'}, 1, true, null, undefined, [1,2,3], 'bc', new String('de'));
// o = {0:'d', 1:'e', 2:3, a:'a'}

如果要将两个对象合并为一个新对象(不影响其中任何一个),请提供{}作为第一个参数

var a={}, b={b:'abc'}, c={c:'cde'}, o;
o = mergeRecursive(a, b, c);
// o===a is true, o===b is false, o===c is false

编辑(由收割者很快):

还要合并阵列

function mergeRecursive(obj1, obj2) {
  if (Array.isArray(obj2)) { return obj1.concat(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 if (Array.isArray(obj2[p])) {
        obj1[p] = obj1[p].concat(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;
}

此解决方案创建一个新对象,并能够处理多个对象。

此外,它是递归的,您可以选择要覆盖值和对象的天气。

    function extendObjects() {

        var newObject        = {};
        var overwriteValues  = false;
        var overwriteObjects = false;

        for ( var indexArgument = 0; indexArgument < arguments.length; indexArgument++ ) {

            if ( typeof arguments[indexArgument] !== 'object' ) {

                if ( arguments[indexArgument] == 'overwriteValues_True' ) {

                    overwriteValues = true;            
                } else if ( arguments[indexArgument] == 'overwriteValues_False' ) {

                    overwriteValues = false;                             
                } else if ( arguments[indexArgument] == 'overwriteObjects_True' ) {

                    overwriteObjects = true;     
                } else if ( arguments[indexArgument] == 'overwriteObjects_False' ) {

                    overwriteObjects = false; 
                }

            } else {

                extendObject( arguments[indexArgument], newObject, overwriteValues, overwriteObjects );
            }

        }

        function extendObject( object, extendedObject, overwriteValues, overwriteObjects ) {

            for ( var indexObject in object ) {

                if ( typeof object[indexObject] === 'object' ) {

                    if ( typeof extendedObject[indexObject] === "undefined" || overwriteObjects ) {
                        extendedObject[indexObject] = object[indexObject];
                    }

                    extendObject( object[indexObject], extendedObject[indexObject], overwriteValues, overwriteObjects );

                } else {

                    if ( typeof extendedObject[indexObject] === "undefined" || overwriteValues ) {
                        extendedObject[indexObject] = object[indexObject];
                    }

                }

            }     

            return extendedObject;

        }

        return newObject;
    }

    var object1           = { a : 1, b : 2, testArr : [888, { innArr : 1 }, 777 ], data : { e : 12, c : { lol : 1 }, rofl : { O : 3 } } };
    var object2           = { a : 6, b : 9, data : { a : 17, b : 18, e : 13, rofl : { O : 99, copter : { mao : 1 } } }, hexa : { tetra : 66 } };
    var object3           = { f : 13, g : 666, a : 333, data : { c : { xD : 45 } }, testArr : [888, { innArr : 3 }, 555 ]  };

    var newExtendedObject = extendObjects( 'overwriteValues_False', 'overwriteObjects_False', object1, object2, object3 );

newExtendedObject的内容:

{"a":1,"b":2,"testArr":[888,{"innArr":1},777],"data":{"e":12,"c":{"lol":1,"xD":45},"rofl":{"O":3,"copter":{"mao":1}},"a":17,"b":18},"hexa":{"tetra":66},"f":13,"g":666}

小提琴:http://jsfiddle.net/o0gb2umb/

A={a:1,b:function(){alert(9)}}
B={a:2,c:3}
A.merge = function(){for(var i in B){A[i]=B[i]}}
A.merge()

结果是:{a:2,c:3,b:function()}