两个对象。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()相同。

有办法做到这一点吗?


当前回答

我把这里所有的答案都看了一遍,然后拼凑出了一个我自己的答案。现有的大多数答案都不是我想要的方式。

这对于2021年来说是相当可怕的,所以任何改善的建议,我都洗耳恭听!

这是在Typescript中

type Props = Record<string, any>

export const deepMerge = (target: Props, ...sources: Props[]): Props => {
  if (!sources.length) {
    return target
  }

  Object.entries(sources.shift() ?? []).forEach(([key, value]) => {
    if (!target[key]) {
      Object.assign(target, { [key]: {} })
    }

    if (
      value.constructor === Object ||
      (value.constructor === Array && value.find(v => v.constructor === Object))
    ) {
      deepMerge(target[key], value)
    } else if (value.constructor === Array) {
      Object.assign(target, {
        [key]: value.find(v => v.constructor === Array)
          ? target[key].concat(value)
          : [...new Set([...target[key], ...value])],
      })
    } else {
      Object.assign(target, { [key]: value })
    }
  })

  return target
}

平面数组使用[…]删除重复值。新的(…)]。

嵌套数组使用concat连接。

其他回答

我发现只有2行解决方案得到深度合并在javascript。一定要告诉我你的结果。

const obj1 = { a: { b: "c", x: "y" } }
const obj2 = { a: { b: "d", e: "f" } }
temp = Object.assign({}, obj1, obj2)
Object.keys(temp).forEach(key => {
    temp[key] = (typeof temp[key] === 'object') ? Object.assign(temp[key], obj1[key], obj2[key]) : temp[key])
}
console.log(temp)

临时对象将打印{a: {b: 'd', e: 'f', x: 'y'}}

我们可以使用$.extend(true,object1,object2)进行深度合并。值true表示递归合并两个对象,修改第一个对象。

美元扩展(真的,目标,对象)

这里,直走;

一个简单的解决方案,工作像Object。仅赋值deep,适用于数组,无需任何修改。

function deepAssign(target, ...sources) { for (source of sources) { for (let k in source) { let vs = source[k], vt = target[k] if (Object(vs) == vs && Object(vt) === vt) { target[k] = deepAssign(vt, vs) continue } target[k] = source[k] } } return target } x = { a: { a: 1 }, b: [1,2] } y = { a: { b: 1 }, b: [3] } z = { c: 3, b: [,,,4] } x = deepAssign(x, y, z) console.log(JSON.stringify(x) === JSON.stringify({ "a": { "a": 1, "b": 1 }, "b": [ 1, 2, null, 4 ], "c": 3 }))

编辑: 我在别的地方回答过一种深度比较两个对象的新方法。 该方法也可以用于深度合并。如果你想要植入,请留言 https://stackoverflow.com/a/71177790/1919821

另一个使用递归的变体,希望你觉得有用。

const merge = (obj1, obj2) => {

    const recursiveMerge = (obj, entries) => {
         for (const [key, value] of entries) {
            if (typeof value === "object") {
               obj[key] = obj[key] ? {...obj[key]} : {};
               recursiveMerge(obj[key], Object.entries(value))
            else {
               obj[key] = value;
            }
          }

          return obj;
    }

    return recursiveMerge(obj1, Object.entries(obj2))
}

deepmerge npm包似乎是解决这个问题使用最广泛的库: https://www.npmjs.com/package/deepmerge