我需要能够在运行时合并两个(非常简单)JavaScript对象。例如,我想:
var obj1 = { food: 'pizza', car: 'ford' }
var obj2 = { animal: 'dog' }
obj1.merge(obj2);
//obj1 now has three properties: food, car, and animal
是否有一种内置的方法来实现这一点?我不需要递归,也不需要合并函数,只需要平面对象上的方法。
我需要能够在运行时合并两个(非常简单)JavaScript对象。例如,我想:
var obj1 = { food: 'pizza', car: 'ford' }
var obj2 = { animal: 'dog' }
obj1.merge(obj2);
//obj1 now has three properties: food, car, and animal
是否有一种内置的方法来实现这一点?我不需要递归,也不需要合并函数,只需要平面对象上的方法。
当前回答
这是我的刺
支持深度合并不改变参数采用任意数量的参数不扩展对象原型不依赖于其他库(jQuery、MooTools、Undercore.js等)包括检查hasOwnProperty短:)/*递归合并财产并返回新对象对象1<;-对象2[<;-…]*/函数合并(){变量dst={},srcp,args=[].splice.call(参数,0);while(参数长度>0){src=参数拼接(0,1)[0];if(toString.call(src)=='[object object]'){for(src中的p){if(src.hasOwnProperty(p)){if(toString.call(src[p])=='[object object]'){dst[p]=合并(dst[p]||{},src[p]);}其他{dst[p]=src[p];}}}}}返回dst;}
例子:
a = {
"p1": "p1a",
"p2": [
"a",
"b",
"c"
],
"p3": true,
"p5": null,
"p6": {
"p61": "p61a",
"p62": "p62a",
"p63": [
"aa",
"bb",
"cc"
],
"p64": {
"p641": "p641a"
}
}
};
b = {
"p1": "p1b",
"p2": [
"d",
"e",
"f"
],
"p3": false,
"p4": true,
"p6": {
"p61": "p61b",
"p64": {
"p642": "p642b"
}
}
};
c = {
"p1": "p1c",
"p3": null,
"p6": {
"p62": "p62c",
"p64": {
"p643": "p641c"
}
}
};
d = merge(a, b, c);
/*
d = {
"p1": "p1c",
"p2": [
"d",
"e",
"f"
],
"p3": null,
"p5": null,
"p6": {
"p61": "p61b",
"p62": "p62c",
"p63": [
"aa",
"bb",
"cc"
],
"p64": {
"p641": "p641a",
"p642": "p642b",
"p643": "p641c"
}
},
"p4": true
};
*/
其他回答
在YUI Y.merge中,应完成以下工作:
Y.merge(obj1, obj2, obj3....)
另一种方法:
function concat_collection(obj1, obj2) {
var i;
var arr = new Array();
var len1 = obj1.length;
for (i=0; i<len1; i++) {
arr.push(obj1[i]);
}
var len2 = obj2.length;
for (i=0; i<len2; i++) {
arr.push(obj2[i]);
}
return arr;
}
var ELEMENTS = concat_collection(A,B);
for(var i = 0; i < ELEMENTS.length; i++) {
alert(ELEMENTS[i].value);
}
如果您需要一个深度合并,它也将通过将数组串联到结果中来“合并”数组,那么这个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;}
请注意,如果只有一个参数传递给此函数,它将充当深度克隆函数。
您可以使用对象排列语法来实现这一点。这是ES2018及以后的一部分。
constobj1={food:“pizza”,car:“ford”};const obj2={animal:“狗”};常量obj3={…obj1,…obj2};console.log(obj3);
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));