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

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

obj1.merge(obj2);

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

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


当前回答

原型具有以下特点:

Object.extend = function(destination,source) {
    for (var property in source)
        destination[property] = source[property];
    return destination;
}

obj1.extend(obj2)将执行您想要的操作。

其他回答

这会将obj合并为“默认”def。obj优先于两者中存在的任何对象,因为obj被复制到def中。还要注意,这是递归的。

function mergeObjs(def, obj) {
    if (typeof obj == 'undefined') {
        return def;
    } else if (typeof def == 'undefined') {
        return obj;
    }
    for (var i in obj) {
        if (obj[i] != null && obj[i].constructor == Object) {
            def[i] = mergeObjs(def[i], obj[i]);
        } else {
            def[i] = obj[i];
        }
    }
    return def;
}

a = {x : {y : [123]}}
b = {x : {z : 123}}
console.log(mergeObjs(a, b));
// {x: {y : [123], z : 123}}

以下两个可能是一个很好的起点。lodash还为那些特殊需求提供定制功能!

_.延伸(http://underscorejs.org/#extend) _.合并(https://lodash.com/docs#merge)

我刚开始使用JavaScript,所以如果我错了,请纠正我。

但如果可以合并任意数量的对象,不是更好吗?下面是我如何使用本机Arguments对象实现的。

关键在于,实际上可以向JavaScript函数传递任意数量的参数,而无需在函数声明中定义它们。如果不使用Arguments对象,就无法访问它们。

function mergeObjects() (
    var tmpObj = {};

    for(var o in arguments) {
        for(var m in arguments[o]) {
            tmpObj[m] = arguments[o][m];
        }
    }
    return tmpObj;
}

哇!这是我在多个页面上看到的第一篇StackOverflow文章。为添加另一个“答案”表示歉意


ES5及更早版本

此方法适用于ES5及更早版本-有许多其他答案可用于ES6。

我没有看到任何利用arguments属性的“深层”对象合并。以下是我的答案-紧凑和递归,允许传递无限的对象参数:

function extend() {
    for (var o = {}, i = 0; i < arguments.length; i++) {
        // Uncomment to skip arguments that are not objects (to prevent errors)
        // if (arguments[i].constructor !== Object) continue;
        for (var k in arguments[i]) {
            if (arguments[i].hasOwnProperty(k)) {
                o[k] = arguments[i][k].constructor === Object
                    ? extend(o[k] || {}, arguments[i][k])
                    : arguments[i][k];
            }
        }
    }
    return o;
}

实例

/***扩展对象*/函数扩展(){对于(var o={},i=0;i<arguments.length;i++){for(自变量[i]中的var k){if(参数[i].hasOwnProperty(k)){o[k]=参数[i][k].构造函数==对象? extend(o[k]||{},参数[i][k]):参数[i][k];}}}返回o;}/***示例*/document.write(JSON.stringify(扩展({api:1,参数:{查询:“hello”}}, {参数:{查询:'there'}})));//输出{“api”:1,“params”:{“query”:“there”}


这个答案现在只是沧海一粟。。。

如果您需要一个深度合并,它也将通过将数组串联到结果中来“合并”数组,那么这个ES6函数可能就是您需要的:

函数deepMerge(a,b){//如果两者都不是对象,请返回其中一个:如果(对象(a)!==a&&对象(b)!==b) 返回b||a;//用空对象/数组替换剩余的基元如果(对象(a)!==a) a=Array.isArray(b)?[] : {};if(对象(b)!==b) b=Array.isArray(a)?[] : {};//区别对待阵列:if(Array.isArray(a)&&Array.isArray(b)){//合并阵列被解释为其深层克隆的串联:return[…a.map(v=>deepMerge(v)),…b.map(v=>deepMerger(v)];}其他{//获取任一对象中存在的键var keys=新集合([…Object.keys(a),…Object.key(b)]);//重复并分配给新对象return Object.assign({},…Array.from(keys,key=>({[key]:deepMerge(a[key],b[key])}));}}//演示的示例数据:变量a={组:[{组:[{name:“John”,年龄:12岁},{name:“Mary”,年龄:20岁}],groupName:'对'}],配置:{颜色:“蓝色”,范围:'远'}};变量b={组:[{组:[{name:'比尔',年龄:15岁}],groupName:'孤独者'}],配置:{范围:'关闭',强度:'平均'}};var merged=deepMerge(a,b);console.log(合并);.作为控制台包装{最大高度:100%!重要;顶部:0;}

请注意,如果只有一个参数传递给此函数,它将充当深度克隆函数。