如何深度合并而不是浅合并?

新手上路,请多包涵

Object.assignObject 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() 相同。

有没有办法做到这一点?

原文由 Mike 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 719
1 个回答

我知道这是一个有点老的问题,但我能想到的 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] } } }

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

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

原文由 Salakar 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
logo
Stack Overflow 翻译
子站问答
访问
宣传栏