EDIT: Thanks 4 all the great, diverse answers - I chose the solution that worked for me even after I realized that I needed more requirements: I also needed new properties to be added and for it to work with arrays in objects as well.
Here's what I wanna do: Update one object through another one.
Here are some constraints:
My Problem is that I don't know how to easily do this for nested objects because typeof x === "object"
also returns true for Date objects for example.
Here's what I got so far:
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);
Currently my updated object looks like this:
{
"dateCreated": "2021-02-10T23:00:00.000Z",
"value": "100",
"subObj": {
"val": 90
}
}
My goal:
{
"dateCreated": "2021-02-10T23:00:00.000Z",
"value": "100",
"subObj": {
"count": 55,
"val": 90
}
}
You could test the constructor of the values like this:
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 updateOriginal = (original, patch) => { Object.entries(patch).forEach(([key, value]) => { value && value.constructor === Object && patch[key]? updateOriginal(original[key], patch[key]): (original[key] = patch[key]); }); } updateOriginal(originalObj, updateObj); console.log(originalObj);
This is the solution you need (from https://gist.github.com/ahtcx/0cd94e62691f539160b32ecda18af3d6 ), actually you can search on google "deep merge" or "recursively merge two javascript objects"
I added ES6 sintax {...obj} to be sure to clone objects before merging them
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 } }; const merge = (target, source) => { // Iterate through `source` properties and if an `Object` set property to merge of `target` and `source` properties for (const key of Object.keys(source)) { if (source[key] instanceof Object) Object.assign(source[key], merge(target[key], source[key])) } // Join `target` and modified `source` Object.assign(target || {}, source) return target } console.log(merge({...originalObj}, {...updateObj}));
You could use recursive approach with reduce
method and for..in
loop and also check if the type of object is Date
. This solution will not work with arrays and also will not modify original data.
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)
This is what worked for me in the past. You can clean it up a little and customize for your purposes but the idea is as follows:
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 mergeDeep(target, source) { 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] }). } } } } function isObject(item) { return (item && typeof item === 'object' &&;Array.isArray(item)); } console,log(originalObj); mergeDeep(originalObj. updateObj); console.log(originalObj);
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.