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

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (2)
  • 关注 (0)
  • 查看 (56)

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具有callprototype功能。例如,arguments变成一个Array可以完成

Array.prototype.slice.call(arguments)

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

这个问题

在DOM的可能AttributeNode遍历特性中使用这种原型/调用模式,或者String为了进行本地对象合并而使用某些泛型函数,有没有一个技巧?

代码看起来像这样:

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

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

一种可能的次优解决方案

如果您可以使用constructoran 的属性,Object然后强制一个对象具有另一个对象的构造函数,然后运行new该复合对象,则可以免费获得合并。但是我并没有完全了解constructorJavaScript中的这个功能的全部含义。

引理

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

你可以将它们连接在一起,然后进行排序,然后进行遍历。但是如果有一个通用的相交位置放在某处,我们可以强制一个数组在本地执行,那将会很不错。

有什么想法吗?

走到一半

对于阵列问题,您可以执行以下操作:

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

尽管如此,它仍然没有完成。

提问于
用户回答回答于

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

没有

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

用户回答回答于

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

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

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.

您可能认为这不是问题,但假设您将此对象用作第三方库的配置。您现在将默认对象和引用的所有内容都控制在第三方库中。

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

扫码关注云+社区