【问题标题】:Add property chain to JS Object将属性链添加到 JS 对象
【发布时间】:2016-09-25 01:31:50
【问题描述】:

是否可以在一行中将一个属性添加到...的添加属性的添加属性中

var some_object = {};
some_object.prop_a = "hi";
some_object.prop_b.prop_c.prop_d = "ho";

虽然第 2 行显然有效,但第 3 行却没有,因为它返回 cannot read property of undefined 错误。我知道,应该分配 prop_d 时, prop_b 和 prop_c 不存在。但是是否有一个简单的单线来做我想做的事情(即添加一个嵌套属性,即使嵌套对象中的某些级别还不存在)?

【问题讨论】:

  • 不,没有。您必须定义要写入的对象。
  • 开箱即用,不,但您当然可以编写一个函数,该函数将采用一系列属性和一个对象,并根据需要添加空对象。
  • 希望很快能支持更多浏览器!这可以使用Proxy 来实现

标签: javascript object


【解决方案1】:

您当然可以编写一个函数来执行此操作。可能是这样的:

function addPropertyChain(chain, val, obj) {
    var propChain = chain.split(".");
    if (propChain.length === 1) {
        obj[propChain[0]] = val;
        return;
    }
    var first = propChain.shift();
    if (!obj[first]) {
        obj[first] = {};
    }    
    addPropertyChain(propChain.join("."), val, obj[first] );
}

var some_object = {};
addPropertyChain("prop_b.prop_c.prop_d","ho",some_object);

console.log(some_object);

【讨论】:

  • 我认为我们对这个问题有相同的想法。干得好。
  • 非常感谢!如果没有其他方法,考虑自己编写一个函数。你的很方便,会被使用!
【解决方案2】:

我知道,应该分配 prop_d 时,prop_b 和 prop_c 不存在。

如果是这种情况,您可以这样做:

some_object.prop_b = {
  prop_c : {
    prop_d : "ho"
  }
};

(或者,在一行中:)

some_object.prop_b = { prop_c : { prop_d : "ho" } };

您只是在使用 JavaScript 的 object initializer syntax 创建嵌套对象。

但是,请注意,如果这些值已经存在,这将覆盖任何现有的 prop_bprop_b.prop_c 值。

【讨论】:

  • 也考虑过,但正如您已经指出的那样,它会覆盖。
【解决方案3】:

您可以在分配之前调用一个方法来确保插槽是一个对象。缺点是您将路径作为字符串提供。你必须走链子。

function ensurePropertyOnObject(o, m)
{
    var props = m.split('.');
    var item;
    var current = o;

    while(item = props.shift()) {
        if(typeof o[item] != 'object') {
            current[item] = {};
        }
        current = o[item];
    }    
}

ensurePropertyOnObject(some_object, "prop_b.prop_c.prop_d");
some_object.prop_b.prop_c.prop_d = "ho";
console.log(some_object);

查看示例:https://jsfiddle.net/ho4k02fr/

【讨论】:

    【解决方案4】:

    为了动态访问和设置对象属性,我发明了两个名为 Object.prototype.setNestedValue()Object.prototype.getNestedValue() 的 Object 方法,您可以在其中提供嵌套属性作为参数。对于Object.prototype.setNestedValue(),最后一个参数是最后设置的值。是这样的;

    Object.prototype.getNestedValue = function(...a) {
      return a.length > 1 ? (this[a[0]] !== void 0 && this[a[0]].getNestedValue(...a.slice(1))) : this[a[0]];
    };
    
    Object.prototype.setNestedValue = function(...a) {
      return a.length > 2 ? typeof this[a[0]] === "object" && this[a[0]] !== null ? this[a[0]].setNestedValue(...a.slice(1))
                                                                                  : (this[a[0]] = typeof a[1] === "string" ? {} : new Array(a[1]),
                                                                                     this[a[0]].setNestedValue(...a.slice(1)))
                          : this[a[0]] = a[1];
    };
    
    var some_object = {};
    some_object.prop_a = "hi";
    some_object.setNestedValue("prop_b","prop_c","prop_d","ho");
    console.log(JSON.stringify(some_object,null,2));

    您还可以添加数组对象。为此,您必须输入数字类型的索引。举个例子吧……

    Object.prototype.getNestedValue = function(...a) {
      return a.length > 1 ? (this[a[0]] !== void 0 && this[a[0]].getNestedValue(...a.slice(1))) : this[a[0]];
    };
    
    Object.prototype.setNestedValue = function(...a) {
      return a.length > 2 ? typeof this[a[0]] === "object" && this[a[0]] !== null ? this[a[0]].setNestedValue(...a.slice(1))
                                                                                  : (this[a[0]] = typeof a[1] === "string" ? {} : new Array(a[1]),
                                                                                     this[a[0]].setNestedValue(...a.slice(1)))
                          : this[a[0]] = a[1];
    };
    
    var some_object = {};
    some_object.prop_a = "hi";
    some_object.setNestedValue("prop_b",3,"prop_d","yay");
    some_object.setNestedValue("prop_b",0,"prop_d","zero this is");
    some_object.setNestedValue("prop_b",1,"prop_d","i am the one");
    some_object.setNestedValue("prop_b","prop_c","prop_d","ho");
    console.log(JSON.stringify(some_object,null,2));

    您会注意到 prop_c 没有被征用,但它仍然作为分配给 prob_b 的数组的属性存在并且完全可以访问。

    【讨论】:

      猜你喜欢
      • 2018-07-27
      • 2015-06-13
      • 2015-09-21
      • 2015-11-15
      • 2013-09-04
      • 2021-03-22
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多