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

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

obj1.merge(obj2);

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

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


当前回答

浅的

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

其他回答

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

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

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

这会将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}}

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.

函数扩展(o,o1,o2){如果(!(o instanceof Object))o={};副本(o,o1);如果(o2)副本(o,o2)函数isObject(obj){var type=Object.protype.toString.call(obj);return obj===对象(obj)&&type!='[object Array]'&&type!='[object函数]';};功能副本(a,b){//将o2复制到ofor(b中的var键)if(b.hasOwnProperty(键)){if(isObject(b[key])){if(!isObject(a[key]))a[key]=Object.assign({},b[key]);其他副本(a[key],b[key])}其他的a[key]=b[key];}}返回o;};变量o1={a:{foo:1},b:1},o2={a:{bar:2},b:[1],c:()=>{}},newMerged=扩展({},o1,o2);console.log(newMerged)控制台日志(o1)控制台日志(o2)