Object.assign和Object spread仅进行浅合并。
问题的一个例子:
// No object nesting
const x = { a: 1 }
const y = { b: 1 }
const z = { ...x, ...y } // { a: 1, b: 1 }
输出是您所期望的。但是,如果我尝试以下方法:
// Object nesting
const x = { a: { a: 1 } }
const y = { a: { b: 1 } }
const z = { ...x, ...y } // { a: { b: 1 } }
而不是
{ a: { a: 1, b: 1 } }
你得到
{ a: { b: 1 } }
X被完全覆盖,因为扩展语法只深入一层。这与Object.assign()
相同。
有办法做到这一点吗?
当涉及到宿主对象或比一包值更复杂的任何类型的对象时,这个问题是非常重要的
另一件需要记住的事情:包含循环的对象图。它通常不难处理——只需保留一组已经访问过的源对象的Set
——但常常被遗忘。
您可能应该编写一个深度合并函数,该函数只期望原始值和简单对象(最多是结构化克隆算法可以处理的类型)作为合并源。如果遇到任何无法处理的问题,或只是通过引用而不是深度合并来分配,则抛出。
换言之,没有一种适合所有人的算法,您要么自己使用,要么寻找一种恰好涵盖您的用例的库方法。
您可以使用Lodash合并:
var object = {
'a': [{ 'b': 2 }, { 'd': 4 }]
};
var other = {
'a': [{ 'c': 3 }, { 'e': 5 }]
};
_.merge(object, other);
// => { 'a': [{ 'b': 2, 'c': 3 }, { 'd': 4, 'e': 5 }] }
我知道这是一个老问题,但ES2015/ES6中我能想到的最简单的解决方案实际上非常简单,使用Object.assign(),
希望这有助于:
/**
* Simple object check.
* @param item
* @returns {boolean}
*/
export function isObject(item) {
return (item && typeof item === 'object' && !Array.isArray(item));
}
/**
* Deep merge two objects.
* @param target
* @param ...sources
*/
export function mergeDeep(target, ...sources) {
if (!sources.length) return target;
const source = sources.shift();
if (isObject(target) && isObject(source)) {
for (const key in source) {
if (isObject(source[key])) {
if (!target[key]) Object.assign(target, { [key]: {} });
mergeDeep(target[key], source[key]);
} else {
Object.assign(target, { [key]: source[key] });
}
}
}
return mergeDeep(target, ...sources);
}
用法示例:
mergeDeep(this, { a: { b: { c: 123 } } });
// or
const merged = mergeDeep({a: 1}, { b : { c: { d: { e: 12345}}}});
console.dir(merged); // { a: 1, b: { c: { d: [Object] } } }
你会在下面的答案中找到一个不可变的版本。
注意,这将导致循环引用上的无限递归。如果你认为你会面临这个问题,这里有一些关于如何检测循环引用的很好的答案。
问题内容: 无论Object.assign和对象传播只能做一浅合并。 问题的一个示例: 输出是您期望的。但是,如果我尝试这样做: 代替 你得到 x完全被覆盖,因为传播语法仅深入了一层。与相同。 有没有办法做到这一点? 问题答案: 有人知道ES6 / ES7规范中是否存在深度合并? 不,不是的。
分支合并分为两种情况,一种是本地分支合并,一种是远程分支合并到本地分支,下面,分别用GIF动画演示 本地合并分支: 远程分支合并
注意 由于JS对象包括的范围非常广,加上ES6又有众多的新特性,很难、也没必要做到囊括所有的类型和情况,这里说的"对象",指的是普通的对象,不包括修改对象原型链, 或者为"Function","Promise"等的情况,请留意。 在ES6中,我们可以很方便的使用Object.assign进行对象合并,但这只是浅层的合并,如果对象的属性为数组或者对象的时候,会导致属性内部的值丢失。 注意: 此处合并
我目前正在迭代一个数组,其中每个索引包含两个节点和一个关系(第1部分)- 我读了这篇文章,但我不明白如何实现它,使两个相同的节点具有相同的ID。我现在的代码是这样的: 创建两个节点 创造他们的关系 将关系添加到节点 坚持使用Neo4jTemplate.save() 我需要更改什么以合并而不是创建?我是否需要在持久化之前进行检查,或者在持久化SDN 4时是否有方法进行检查? 编辑: 我决定使用Neo
问题内容: 通常我会使用浅拷贝对象 这是一个例子: 将给我们: 但是,如果我想合并对象以使父键不会被子对象覆盖,该怎么办: 将给我们: 是否有一个Angular函数已经执行了我不知道的深度合并? 如果不是,则有一种本机方法可以在javascript中递归地执行n个级别的操作。 问题答案: Angular 1.4或更高版本 用途: 不同于,递归地进入源对象的对象属性,执行深层复制。 旧版本的Angu
问题内容: Python中是否有一个可用于深度合并字典的库: 以下: 当我结合时,我希望它看起来像: 问题答案: 我希望我不会重新发明轮子,但是解决方案相当短。而且,超级有趣的代码。 因此,其想法是将源复制到目标,并且每次源中的命令都进行递归。因此,如果在A中给定元素包含字典而在B中包含任何其他类型,则确实存在错误。