问题
I have an object with objects, which are basically settings per guild. In these objects are various configuration options that the admin of their guild can change.
{
"1": {
"foo": "Hello World",
"bar": "Ello World",
"roo": {
"doo": "oof"
}
},
"2": {
"foo": "foo bar foo bar",
"bar": "World! Hi!",
"roo": {
"doo": "boo!"
}
}
}
And I have a default object for those settings.
const Default = {
foo: "Hello, World!",
bar: "Foo example",
roo: {
doo: "boo"
}
};
When I add a new key to the default object, I'd like all the objects in the settings to adapt to these new changes and add only the new key with the default value. Although, I don't know which key is new, because only at startup I want the script to check for new values and add those to the existing settings.
Also, settings can have nested objects but no arrays - arrays are only used as value. I've looked at this answer but I cannot seem to figure out how to add nested object support
For instance, I could add a "foobarexample"
key to the default object, and as default value "ello"
and it would add that to all the settings. I should also be able to add this to the 'roo' object and it would still update, even though 'roo' isn't new
If you have any suggestions, they're much appreciated! Thanks
回答1:
This is a perfect use case for JavaScript's prototypal inheritance:
const defaultObj = {
foo: "Hello, World!",
bar: "Foo example",
roo: {
doo: "boo"
}
};
const obj = Object.assign(Object.create(defaultObj), { foo: "New foo" });
const anotherObj = Object.create(defaultObj);
console.log('obj.foo', obj.foo);
console.log('anotherObj.foo', anotherObj.foo);
console.log('obj.bar', obj.bar);
defaultObj.bar = "New bar";
console.log('obj.bar', obj.bar);
console.log('anotherObj.bar', anotherObj.bar);
defaultObj.foobarexample = "ello";
console.log('obj.foobarexample ', obj.foobarexample );
console.log('anotherObj.foobarexample ', anotherObj.foobarexample );
In this code, all of the objects created from defaultObj
with Object.create
have a reference on defaultObj
. When trying to access a property of the resulting objects, the property will be looked up in the object itself, and then in defaultObj
if not found. defaultObj
can safely be mutated after the objects have been created (it cannot be reassigned though, because the objects created would keep a reference on the previous one).
回答2:
https://repl.it/@HenriDe/httpsreplitHenriDeIntersectinobjectswithdefault
this one should work for what you are looking for.
const defaultValues = {
"1" : {
foo: 'Hello, World!',
bar: 'Foo example',
roo: {
doo: 'boo',
newest: {
goal: "dodo"
}
},
hello: "world"
}
};
function eachRecursive(obj, defaultValues, level = 0){
// check each key amongst the defaults
for (var k in defaultValues){
// if our original object does not have key attach it + default values associated
if (!obj.hasOwnProperty(k)) {
obj[k] = checkWith[k]
}
// keep calling as long as value is object
if (typeof obj[k] == "object" && obj[k] !== null)
eachRecursive(obj[k], checkWith[k], level + 1);
}
}
}
// for each of the specific entries check
for (let [key, value] of Object.entries(data)) {
eachRecursive(data[key], defaultValues["1"])
}
console.log(data["1"])
来源:https://stackoverflow.com/questions/62178687/intersecting-objects-with-a-default-object-in-javascript