首页 > 解决方案 > 更新嵌套的 JS 对象而不覆盖缺失的属性

问题描述

编辑:感谢 4 所有出色而多样的答案 - 即使在我意识到我需要更多要求之后,我还是选择了对我有用的解决方案:我还需要添加新属性,并且它也需要与对象中的数组一起使用。

这就是我想做的:通过另一个对象更新一个对象。
以下是一些限制条件:

我的问题是我不知道如何轻松地为嵌套对象执行此操作,因为typeof x === "object"例如 Date 对象也返回 true。

这是我到目前为止得到的:

let originalObj = {
  dateCreated: new Date(2021, 1, 10),
  value: "100",
  subObj: {
    count: 55,
    val: null
  }
};

let updateObj = {
  dateCreated: new Date(2021, 1, 11),
  subObj: {
    val: 90
  }
};

let updateOrignal = (oObj, uObj) => {
  for (let prop in uObj) {
    if (uObj.hasOwnProperty(prop) &&
      oObj.hasOwnProperty(prop)) {
      oObj[prop] = uObj[prop];
    }
  }
};

console.log(originalObj);
updateOrignal(originalObj, updateObj)
console.log(originalObj);

目前我更新的对象如下所示:

{
  "dateCreated": "2021-02-10T23:00:00.000Z",
  "value": "100",
  "subObj": {
    "val": 90
  }
}

我的目标:

{
  "dateCreated": "2021-02-10T23:00:00.000Z",
  "value": "100",
  "subObj": {
    "count": 55,
    "val": 90
  }
}

标签: javascript

解决方案


您可以将递归方法与reduce方法和for..in循环一起使用,并检查对象的类型是否为Date. 此解决方案不适用于数组,也不会修改原始数据。

let originalObj = {
  dateCreated: new Date(2021, 1, 10),
  value: "100",
  subObj: {
    count: 55,
    val: null
  }
};

let updateObj = {
  dateCreated: new Date(2021, 1, 11),
  subObj: {
    val: 90
  }
};

function update(o1, o2) {
  return Object.entries(o1).reduce((r, e) => {
    for (let p in o2) {
      if ([o1[p], o2[p]].every(o => typeof o === 'object')) {
        r[p] = o2[p] instanceof Date ? o2[p] : update(r[p], o2[p])
      } else {
        r[p] = o2[p]
      }
    }

    return r
  }, { ...o1 })
}

const result = update(originalObj, updateObj)

console.log(result)


推荐阅读