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

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

obj1.merge(obj2);

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

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


当前回答

Use:

//Takes any number of objects and returns one merged object
var objectMerge = function(){
    var out = {};
    if(!arguments.length)
        return out;
    for(var i=0; i<arguments.length; i++) {
        for(var key in arguments[i]){
            out[key] = arguments[i][key];
        }
    }
    return out;
}

测试方法:

console.log(objectMerge({a:1, b:2}, {a:2, c:4}));

结果是:

{ a: 2, b: 2, c: 4 }

其他回答

应修改给定的解决方案以检查for中的source.hasOwnProperty(属性)。。在赋值之前的循环中-否则,您最终会复制整个原型链的财产,这是很少需要的。。。

顺便说一句,你们正在做的是覆盖财产,而不是合并。。。

这就是JavaScript对象区域真正合并的方式:只有to对象中不是对象本身的键才会被from覆盖。其他一切都将被真正合并。当然,您可以将此行为更改为不覆盖任何存在的内容,例如仅当to[n]未定义时,等等…:

var realMerge = function (to, from) {

    for (n in from) {

        if (typeof to[n] != 'object') {
            to[n] = from[n];
        } else if (typeof from[n] == 'object') {
            to[n] = realMerge(to[n], from[n]);
        }
    }
    return to;
};

用法:

var merged = realMerge(obj1, obj2);

可以使用Object.assign方法。例如:

var result = Object.assign(obj1, obj2);

此外,请注意,它会创建对象的浅副本。

我使用Object.create()来保持默认设置(使用__proto__或Object.getPrototypeOf())。

function myPlugin( settings ){
    var defaults = {
        "keyName": [ "string 1", "string 2" ]
    }
    var options = Object.create( defaults );
    for (var key in settings) { options[key] = settings[key]; }
}
myPlugin( { "keyName": ["string 3", "string 4" ] } );

这样我以后就可以一直使用“concat()”或“push()”。

var newArray = options['keyName'].concat( options.__proto__['keyName'] );

注意:为了避免重复,需要在连接之前进行hasOwnProperty检查。

值得一提的是,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。