【问题标题】:Deeply assign JavaScript object literal [duplicate]深度分配 JavaScript 对象字面量 [重复]
【发布时间】:2016-06-15 19:02:15
【问题描述】:

我正在尝试在对象中深入分配一个值。例如:

const errors = {}
if(errorOnSpecificField) {
  // TypeError: Cannot read property 'subSubCategory' of undefined(…)
  errors.subCategory.subSubCategory.fieldWithError = 'Error Message'
}

现在,没有 lodash,我可以做到:

const errors = {}
if(errorOnSpecificField) {
    errors.subCategory = errors.SubCategory || {}
    errors.subCategory.subSubCategory = errors.SubCategory.subSubCategory || {}
    errors.subCategory.subSubCategory.fieldWithError = 'Error Message'
}

使用 lodash,我可以做到这一点:

const errors = {}
if(errorOnSpecificField) {
    _.set(errors, 'subCategory.subSubCategory.fieldWithError', 'Error Message');
}

我试图避免使用第三方库。有没有更优雅的解决方案,尤其是现在 es2015 有对象解构。逆运算很简单:

  let {subCategory : {subSubCategory: {fieldWithError}}} = errors

什么是深度对象分配的优雅解决方案?谢谢!

【问题讨论】:

  • Object.assign() ? - 它会覆盖所有属性
  • 正如你所提到的,因为它覆盖了已经设置的其他属性,所以这不适用于我的情况
  • 然后您可能会寻找许多 extend 实现中的一些实现
  • 呃,为什么不直接使用errors.subCategory = {subSubCategory: {fieldWithError: 'Error Message'}}?这与解构完全相反。
  • 问题是如果我已经定义了其他 subSubCategories,它会覆盖它们

标签: javascript ecmascript-6


【解决方案1】:

这是一种安全地分配给深层对象的相当易读的方法:

(((errors||{}).subCategory||{}).subSubCategory||{}).fieldWithError = 'Error Message'

如果它尚不存在,则不会创建 errors.subCategory.subSubCategory

【讨论】:

  • 这实际上不适用于分配。对于访问,可以,但不能用于创建属性。
  • 嗯...它不会创建errors.subCategory.subSubCategory,但如果它已经存在,它会安全地分配给它。
【解决方案2】:

简短的回答,不,没有为它编写方法就没有干净的方法(你可以只使用 lodash 中的方法而不导入整个库)

...然而...

警告这只是为了好玩。不要在生产环境中尝试这个(req es6)。

Object.prototype.chainSet = function() {
  let handler = {
    get (target, name) {
      if (!(name in target)) {
        target[name] = new Proxy({}, handler)
      }
      return target[name]
    }
  }

  return new Proxy(this, handler)
}

使用:

let a = {}
a.chainSet().foo.bar.baz = 1
a.foo.bar.baz // => 1

【讨论】:

    【解决方案3】:

    Object.assign() 可以满足您的要求。

    let errors = { otherField: "value" };
    let newobj = {subCategory : {subSubCategory: {fieldWithError: "Error goes here"}}};
    Object.assign(errors, newobj);
    

    这会产生:

    {
      otherField:'value',
      subCategory: {
        subSubCategory: {
          fieldWithError:'Error goes here'
        }
      }
    }
    

    【讨论】:

    • 如果errors = {subCategory: {x: "y"}} 并且您分配了newobj,则属性x 被“删除”(整个subCategory 对象被换出)。 OP 正在寻找避免这种情况的方法。
    【解决方案4】:

    您可以尝试以下方法:

    function ErrorRegistry(obj)
    {
        this.errors = obj || {};
        this.addError = function(k, msg)
        {
            var keys = k.split('.');
            var o = this.errors;
            for(var i = 0, l = keys.length, last = l-1; i<l; i++)
            {
                if(typeof o[keys[i]] === 'undefined')
                    o[keys[i]] = {};
                if(i == last)
                    o[keys[i]] = msg;
                else
                    o = o[keys[i]];
            }
        };
    }
    var errors = {'subCategory1':{'fieldWithError1':'Error1'}};
    var errorRegistry = new ErrorRegistry(errors);
    errorRegistry.addError('subCategory1.fieldWithError2', "Error2");
    errorRegistry.addError('subCategory1.subSubCategory1.fieldWithError3', "Error3");
    errorRegistry.addError('subCategory1.subSubCategory2.fieldWithError4', "Error4");
    errors = errorRegistry.errors;
    console.log(errors);
    

    【讨论】:

      猜你喜欢
      • 2012-07-03
      • 2012-10-15
      • 2021-01-01
      • 1970-01-01
      • 2020-02-21
      • 1970-01-01
      • 1970-01-01
      • 2015-05-06
      • 1970-01-01
      相关资源
      最近更新 更多