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

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

obj1.merge(obj2);

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

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


当前回答

JSON兼容JavaScript对象的合并

我鼓励使用和利用不修改原始源代码的非破坏性方法,“Object.assign”是一种破坏性的方法,而且它也不太适合生产,因为它在早期浏览器上停止工作,而且你没有办法用其他方法对它进行干净的修补。

无论采用何种解决方案,合并JS对象都将永远无法实现或不完整。但是,合并JSON兼容的兼容对象离能够编写一段简单且可移植的代码只有一步之遥。该代码是一种非破坏性方法,将一系列JS对象合并到一个返回的主对象中,该主对象包含所有唯一的属性名及其对应的值,这些属性名合成在一个主对象中用于预期目的。

考虑到MSIE8是第一个为JSON对象添加本地支持的浏览器,这是一种极大的解脱,重用现有技术始终是一个受欢迎的机会。

将代码限制为JSON兼容的标准对象,与其说是限制,不如说是优势,因为这些对象也可以通过互联网传输。当然,对于那些想要更深入的向后兼容性的人来说,总是有一个json插件。,其方法可以很容易地分配给外部代码中的JSON变量,而无需修改或重写正在使用的方法。

function Merge( ){
    var a = [].slice.call( arguments ), i = 0;
        while( a[i] )a[i] = JSON.stringify( a[i++] ).slice( 1,-1 );
        return JSON.parse( "{"+ a.join() +"}" );
    }

(当然,人们总是可以给它取一个更有意义的名字,我还没有决定;应该把它命名为JSONmerge)

用例:

var master = Merge( obj1, obj2, obj3, ...objn );

现在,与Object.assign相反,这将使所有对象保持不变,并保持其原始状态(以防您做错了什么,需要重新排序合并对象,或者在再次合并之前能够将它们单独用于其他操作)。

Merge参数的数量也仅受参数长度限制[这是巨大的]的限制。本机支持的JSON parse/stringify已经进行了机器优化,这意味着:它应该比任何脚本形式的JS循环都快。对给定参数的迭代是使用while完成的,while被证明是JS中最快的循环。

简单地提一下我们已经知道的事实,即唯一对象标签(键)的重复财产将被包含相同键标签的后一个对象覆盖,这并不有害,这意味着您可以通过简单地对参数列表进行排序或重新排序来控制哪个属性将取代前一个属性。以及获得一个干净且更新的主对象而无重复作为最终输出的好处。

;var obj1={a:1},obj2={b:2},obj3={c:3};函数合并(){var a=[].slice.call(参数),i=0;而(a[i])a[i]=JSON.stringify(a[i++]).slice(1,-1);return JSON.parse(“{”+a.join()+“}”);};var master=合并(obj1、obj2、obj3);console.log(JSON.stringify(master));

其他回答

**使用Object.assign或排列合并对象很简单。。。操作员**

var obj1={food:“pizza”,car:“ford”}var obj2={animal:“狗”,car:“宝马”}var obj3={a:“a”}var mergedObj=对象赋值(obj1、obj2、obj3)//或使用Spread操作符(…)var mergedObj={…obj1,…obj2,…obj3}console.log(mergedObj);

对象从右向左合并,这意味着与右侧对象具有相同财产的对象将被覆盖。

在此示例中,obj2.car覆盖obj1.car

jQuery还有一个实用程序:http://api.jquery.com/jQuery.extend/.

摘自jQuery文档:

// Merge options object into settings object
var settings = { validate: false, limit: 5, name: "foo" };
var options  = { validate: true, name: "bar" };
jQuery.extend(settings, options);

// Now the content of settings object is the following:
// { validate: true, limit: 5, name: "bar" }

上面的代码将改变现有的名为setting的对象。


如果要在不修改任何参数的情况下创建新对象,请使用以下命令:

var defaults = { validate: false, limit: 5, name: "foo" };
var options = { validate: true, name: "bar" };

/* Merge defaults and options, without modifying defaults */
var settings = $.extend({}, defaults, options);

// The content of settings variable is now the following:
// {validate: true, limit: 5, name: "bar"}
// The 'defaults' and 'options' variables remained the same.

在MooTools中,有Object.merge():

Object.merge(obj1, obj2);

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

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 }