Intersecting objects with a default object in JavaScript

淺唱寂寞╮ 提交于 2020-06-17 13:18:04

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!