为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

ABOUTYOU 2019-06-19 19:42:44
如何进行深度合并而不是浅层合并?双管齐下对象.分配和对象传播只做浅合并。这个问题的一个例子是:// 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().有办法吗?
查看完整描述

3 回答

?
慕慕森

TA贡献1856条经验 获得超17个赞

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

不,没有。


查看完整回答
反对 回复 2019-06-19
?
繁星点点滴滴

TA贡献1803条经验 获得超3个赞

我知道这是个老生常谈的问题,但在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] } } }

您将在下面的答案中找到这个不变的版本。

请注意,这将导致循环引用的无限递归。关于如何检测循环引用,如果您认为您会面临这个问题,这里有一些很好的答案。


查看完整回答
反对 回复 2019-06-19
?
慕容森

TA贡献1853条经验 获得超18个赞

当涉及到宿主对象或任何比一袋值更复杂的对象时,这个问题是不平凡的。

  • 您是调用getter来获取值,还是对属性描述符进行复制?
  • 如果合并目标有一个setter(要么拥有属性,要么在它的原型链中)怎么办?您认为值已经存在还是调用setter来更新当前值?
  • 您是调用自己的属性函数还是复制它们?如果它们是绑定函数或箭头函数,这取决于它们定义时作用域链中的某些内容?
  • 如果它类似于DOM节点呢?当然,您不希望将其视为简单对象,而只是将其所有属性深度合并到
  • 如何处理数组、映射或集合等“简单”结构?考虑他们-现在还是合并他们?
  • 如何处理不可枚举的自身属性?
  • 新的子树呢?简单地指定引用还是深克隆?
  • 如何处理冻结/密封/不可扩展的对象?

要记住的另一件事是:包含循环的对象图。通常情况下,这并不难处理-只需保留一个Set已经访问过的源对象-但经常被遗忘。

您可能应该编写一个深度合并函数,它只需要原始值和简单对象-最多是那些结构化克隆算法-作为合并来源。如果遇到任何无法处理或仅通过引用分配而不是深度合并的内容,则抛出。

换句话说,没有一刀切的算法,你要么必须自己滚动,要么寻找一个恰巧涵盖了你的用例的库方法。


查看完整回答
反对 回复 2019-06-19
  • 3 回答
  • 0 关注
  • 1023 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信