I have a complex question that I can't figure out the answer to. So in my Discord bot, I have a little object called config
. I also have a baseConfig
object, which are the defaults used when the bot is added to a new server. Sometimes, I update my bot in a way that requires a new config value- I want to be able to add it to baseConfig
and have the new key reflected across config
. (In reality the config object has nested objects for different guilds, but I'm writing it in a way where this is irrelevant). As an example, let's say obj1
is a config, and obj2
is the base config.
let obj1 = {
emojiSettings: {
success: ":success:",
error: ":error:"
},
warnSettings: {
muteThreshold: 3,
expireHours: 48
}
}
Let's say I update obj2
with a brand new config:
// defaults
let obj2 = {
emojiSettings: {
success: ":defaultSuccess:"
error: ":defaultError:"
}
warnSettings: {
muteThreshold: 2,
expireHours: 24
}
newConfig: {
newOption: 4
}
}
I want all the settings in obj1
to stay the same, but add the objects and keys that were updated in obj2
.
CodePudding user response:
I would write a function to deeply compare the two that iterates over every property. If the property doesn't exist in obj1, it adds it. If the property does exist in obj1, it checks to see if that property is an object (but not an array), and, if it is, the function recursively calls itself.
const updateObject = (o1, o2) => {
Object.entries(o2).forEach((prop) => {
const propName = prop[0];
if (!o1[propName]) {
if (typeof o2[propName] !== 'object' || Array.isArray(o2[propName])) {
o1[propName] = o2[propName];
} else {
o1[propName] = { ...o2[propName] };
}
} else if (typeof o2[propName] === 'object' && !Array.isArray(o2[propName])) {
updateObject(o1[propName], o2[propName]);
}
});
};
updateObject(obj1, obj2);