猿问

如何进行深度合并而不是浅层合并?

如何进行深度合并而不是浅层合并?

双管齐下对象.分配对象传播只做浅合并。

这个问题的一个例子是:

// No object nestingconst x = { a: 1 }const y = { b: 1 }const z = { ...x, ...y } // { a: 1, b: 1 }

输出就是你所期望的。然而,如果我尝试这样做:

// Object nestingconst 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().

有办法吗?



ABOUTYOU
浏览 1024回答 3
3回答

慕慕森

有没有人知道ES6/ES7规范中是否存在深度合并?不,没有。

繁星点点滴滴

我知道这是个老生常谈的问题,但在ES 2015/ES6中,我能想到的最简单的解决方案其实是非常简单的,使用Object.Ast(),希望这有助于:/**  * 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 } } });// orconst merged = mergeDeep({a: 1}, { b : { c: { d: { e: 12345}}}});   console.dir(merged); // { a: 1, b: { c: { d: [Object] } } }您将在下面的答案中找到这个不变的版本。请注意,这将导致循环引用的无限递归。关于如何检测循环引用,如果您认为您会面临这个问题,这里有一些很好的答案。

慕容森

当涉及到宿主对象或任何比一袋值更复杂的对象时,这个问题是不平凡的。您是调用getter来获取值,还是对属性描述符进行复制?如果合并目标有一个setter(要么拥有属性,要么在它的原型链中)怎么办?您认为值已经存在还是调用setter来更新当前值?您是调用自己的属性函数还是复制它们?如果它们是绑定函数或箭头函数,这取决于它们定义时作用域链中的某些内容?如果它类似于DOM节点呢?当然,您不希望将其视为简单对象,而只是将其所有属性深度合并到如何处理数组、映射或集合等“简单”结构?考虑他们-现在还是合并他们?如何处理不可枚举的自身属性?新的子树呢?简单地指定引用还是深克隆?如何处理冻结/密封/不可扩展的对象?要记住的另一件事是:包含循环的对象图。通常情况下,这并不难处理-只需保留一个Set已经访问过的源对象-但经常被遗忘。您可能应该编写一个深度合并函数,它只需要原始值和简单对象-最多是那些结构化克隆算法-作为合并来源。如果遇到任何无法处理或仅通过引用分配而不是深度合并的内容,则抛出。换句话说,没有一刀切的算法,你要么必须自己滚动,要么寻找一个恰巧涵盖了你的用例的库方法。
随时随地看视频慕课网APP

相关分类

JavaScript
我要回答