原生的方式来合并在Javascript中的对象

Javascript的对象没有任何本地合并操作。 如果你有两个对象,说

{a:1, b:2} {c:3, d:4} 

并想要得到

 {a:1, b:2, c:3, d:4} 

据我所知,你必须迭代对象。 也就是说,你决定合并左边还是合并右边的策略,然后你做一些像(简化)

 for (key in object2) { object1[key] = object2[key]; } 

这可以。 但是,JavaScript具有callprototypefunction。 例如,将arguments转换成一个Array可以完成

Array.prototype.slice.call(arguments)

这种方法利用了现有的本地代码,因此不易受程序员愚蠢的影响,而且运行速度比非本地实现要快。

这个问题

在DOM的AttributeNode遍历function上使用这个原型/调用模式,或者为了做一个本地对象合并而使用一些通用的String函数,有没有一个技巧?

代码看起来像这样:

var merged = somethingrandom.obscuremethod.call(object1, object2)

结果,你会得到一个没有遍历的本地合并。

一个可能的,次优的解决scheme

如果您可以使用Objectconstructor属性,然后强制一个对象具有另一个对象的构造函数,然后在复合对象上运行new的对象,则可以免费获得合并。 但是我没有牢牢把握JavaScript中的constructor的全部含义来完成这个调用。

引理

同样的问题也适用于Arrays 。 一个常见的问题是取7个数组,然后尝试找出这些数组的交集。 也就是说,所有7个数组中存在哪个数字。

你可以将它们连接在一起,然后做一个sorting,然后做一个遍历。 但是如果有一个通用的相交位置,我们可以强制一个数组在本地执行,那将会很好。

有什么想法吗?

编辑:

到达那里的一半

对于数组问题,您可以执行以下操作:

array.concat(a,b,c).sort()。join(':'),然后使用一些棘手的RegExp捕获和重复模式来遍历。 RegExp的实现,如果你不知道,运行在一个非常简单的基于栈的虚拟机上。 当你初始化你的正则expression式,这实际上是一个被编译的程序(RegExp.compile是一个不推荐使用的JS方法)。 然后,当地人以一种极快的方式跑过绳子。 也许你可以利用这个成员的门槛,并取得更好的performance…

它仍然不是所有的方式。

我对此的回答将令人失望,但仍然是:

没有

原因很简单:Resig先生在jQuery中实现合并(或者称为“扩展”)是循环的,就像你的问题一样。 你可以在这里看看。 我敢说,如果John Resig没有find一个聪明的内build方式来做到这一点,那么简单的计算器也不会:)

百万美元的问题! 我已经尝试了很多方法,上面描述的循环方式总是看起来最肮脏。 ES6的Object.setPrototypeOf()允许你将一个“属性重写”对象委托给一个“默认属性”对象,几乎完成了你想要做的事情,但是使用Object.setPrototypeOf()有一些严重的含义,比如禁用浏览器对整个脚本的编译器优化。

另外,在循环解决scheme和Object.setPrototypeOf()解决scheme中,您都会遇到“属性覆盖”对象可以改变“默认属性”对象的情况:

 defaultObj = { a: [1, 2] } ... overrideObj = { b: 3 } Object.setPrototypeOf(overrideObj, defaultObj); console.log(overrideObj); // {a: [1, 2], b: 3} // Great! ... overrideObj.a.push(4); console.log(defaultObj); // {a: [1, 2, 4]} // Uh-oh. 

您可能会认为这不是问题,但假设您将此对象用作第三方库的configuration。 您现在将默认对象的控制权以及其中引用的所有内容交给第三方库。

更好的解决scheme可能是使用JSON.stringify和JSON.parse来复制和组合对象。 这里有一个Gist的例子: https : //gist.github.com/spikesagal/6f7822466887f19b9c65

HTH

不是我所知道的,不是。 此外,你会想要写这样的合并方法:

 function mergeInto(o1, o2) { if (o1 == null || o2 == null) return o1; for (var key in o2) if (o2.hasOwnProperty(key)) o1[key] = o2[key]; return o1; } 

您可以使用原生JS 1.7来执行以下操作,而无需使用框架。 请参阅小提琴示例(仅用于简单对象的示例 – 不是复杂的嵌套对象)

 var obj1 = {a: "a", b: "b"}; var obj2 = {c: "c", d: "d"}; // The magic: ugly but works perfectly var value = (JSON.stringify(obj1).concat(JSON.stringify(obj2))).replace("}{", ","); document.getElementById("lbl1").setAttribute("value", value); // back to object var obj3 = JSON.parse(value); document.getElementById("lbl2").setAttribute("value", obj3.a + " " + obj3.b + " " + obj3.c + " " + obj3.d); 

使用ES6(ES2015)可以使用Object.assign方法:

 var x = {a:1, b:2}; var y = {c:3, d:4}; var z = Object.assign({},x,y); 

使用ES7(ES2016,Chrome 60+或Babel),您可以使用Object spread运算符

 var x = {a:1, b:2}; var y = {c:3, d:4}; var z = {...x, ...y}; 

在ECMA-Script中没有本地方式,请使用:

 function merge(o1,o2) { if (typeof(o1)!=='object') o1={}; if (typeof(o2)!=='object') o2={}; for (var k in o2) { if (o1[k]!==undefined) alert ('Collision Error'); // TODO else o1[k]=o2[k]; } return o1; } 

这是一个你可以用来解决你的困境的function。

码:

  var a = {'a':'1', 'b':'2'}; var b = {'c':'3', 'd':'4'}; function appendObj(a,b) { var aZ = 'abcdefghijklmnopqrstuvwxyz'.split(''); bKeys = Object.keys(b); for (var i = 0; i < bKeys.length; i++) { a[bKeys[i]] = b[bKeys[i]]; } return a; } var newObj = appendObj(a,b); console.log(newObj) 

我希望这有帮助。

注意我通过手机input了这个信息,所以如果有语义错误或拼写错误,我很抱歉。

祝一切顺利,

马特

下面我介绍了一个我写的深度合并函数。 它不会深度合并数组,只有对象。 它将需要两个对象,并返回第三个新的对象。

 var merge = function(o1, o2) { var o_new = {}; for(p in o1) { if(o1[p]) { if(typeof o1[p] == 'object' && !(o1[p] instanceof Array) && o2.hasOwnProperty(p)) { o_new[p] = merge(o1[p], o2[p]); } else { o_new[p] = o1[p]; } } } for(p in o2) { if(typeof o2[p] == 'object' && !(o2[p] instanceof Array) && o1.hasOwnProperty(p)) { o_new[p] = merge(o1[p], o2[p]); } else { o_new[p] = o2[p]; } } return o_new; }