【问题标题】:Intersecting objects with a default object in JavaScript将对象与 JavaScript 中的默认对象相交
【发布时间】:2020-06-03 17:12:12
【问题描述】:

我有一个带有对象的对象,这些对象基本上是每个公会的设置。在这些对象中有各种配置选项,他们的公会管理员可以更改。

{
  "1": {
    "foo": "Hello World",
    "bar": "Ello World",
    "roo": {
      "doo": "oof"
    }
  },
  "2": {
    "foo": "foo bar foo bar",
    "bar": "World! Hi!",
    "roo": {
      "doo": "boo!"
    }
  }
}

我有一个用于这些设置的默认对象。

const Default = {
  foo: "Hello, World!",
  bar: "Foo example",
  roo: {
    doo: "boo"
  }
};

当我向默认对象添加新键时,我希望设置中的所有对象都适应这些新更改并仅添加具有默认值的新键。虽然,我不知道哪个键是新的,因为只有在启动时我才希望脚本检查新值并将其添加到现有设置中。

此外,设置可以有嵌套对象但没有数组 - 数组仅用作值。我查看了this answer,但似乎无法弄清楚如何添加嵌套对象支持

例如,我可以将"foobarexample" 键添加到默认对象,并将"ello" 作为默认值添加到所有设置中。我也应该能够将它添加到“roo”对象中,并且它仍然会更新,即使“roo”不是新的

如果您有任何建议,我们将不胜感激!谢谢

【问题讨论】:

    标签: javascript node.js object


    【解决方案1】:

    这是 JavaScript 原型继承的完美用例:

    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 );

    在这段代码中,从defaultObjObject.create 创建的所有对象都有defaultObj 的引用。当尝试访问结果对象的属性时,将在对象本身中查找该属性,如果未找到则在defaultObj 中查找。 defaultObj 可以在创建对象后安全地进行变异(但不能重新分配,因为创建的对象会保留对前一个对象的引用)。

    【讨论】:

    • "这是原型继承的完美用例" - 是的。但是为什么要使用new Default() 构造函数呢?去Object.create吧。
    • 感谢您的解决方案!我明白你是怎么做到的,它工作得非常完美:]
    【解决方案2】:

    https://repl.it/@HenriDe/httpsreplitHenriDeIntersectinobjectswithdefault

    这个应该可以满足您的需求。

    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"])
    

    【讨论】:

    • 鼓励答案中的链接用于背景和澄清,但即使链接停止工作,答案也应该回答问题。
    • 有一些语法错误,checkWith 未定义,但我让它工作了,但 roo 的内容没有更新,hello 未定义,但这可能是因为我刚刚在函数头中初始化了let checkWith = {};。你能更新你的答案吗?
    • 根据您的链接的域/URL 与您的用户名相同或包含您的用户名,您似乎已链接到您自己的网站/您所属的网站。如果这样做,您必须在您的帖子中披露这是您的网站。如果您不披露从属关系,则将其视为垃圾邮件。请参阅:What signifies "Good" self promotion?the help center on self-promotion。披露必须是明确的,但不需要是正式的。如果是您自己的个人内容,则可以是“在我的网站上……”、“在我的博客上……”等。
    • 要么答案不完整,因为缺少变量,要么你根本没有测试它/忘记包含一些东西,@Henri De Bel。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-11-24
    • 2014-08-12
    • 1970-01-01
    • 2019-02-20
    • 2018-03-19
    相关资源
    最近更新 更多