使用直到第n级的子对象创建对象

时间:2016-09-15 22:57:52

标签: javascript

我有一个名为 MyObject 的对象和一个名为 createEntry() 的方法,旨在为 {{1}创建一个新属性和属性的子属性,如果它已经存在,则完全跳过它。

我的代码:

MyObject

如上面的函数所示,我正在尝试为方法 var MyObject = { createEntry: function (val1, val2, val3, val4) { this[val1] = this[val1] || {}; this[val1][val2] = this[val1][val2] || {}; this[val1][val2][val3] = val4; } }; MyObject.createEntry("val1", "val2", "val3", "val4"); 的每个参数创建一个新的子对象,除了最后两个,其中 { {1}} createEntry() val3 property 是其值。

当我的方法处于当前状态时,我只能达到3级,其后续的需要更长和更长的代码。我假设使用 method 循环可以实现上述目标,但我还没有弄明白。

问题:如何根据上面函数传递的参数数量创建无限制的子对象,树形方式如下所示:

val4

3 个答案:

答案 0 :(得分:4)

reduceRight似乎是完美的:

function createEntry(...args) {
  return args.reduceRight(function(prev, curr) {
    return {[curr]: prev};
  });
}
console.log(createEntry("val1", "val2", "val3", "val4"));

答案 1 :(得分:1)

好吧,当使用参数创建无限的子对象时,我会迭代每个参数,将我输入的最后一个对象作为参考。这段代码足以理解。

注意:Object.assign是一个新的浏览器实现,但它已经有polyfills。当对象中已存在条目名称时,我使用此方法将对象与对象连接起来

Object['prototype']['createEntries'] = function() {
    /* store last object location */
    var lastObj = this

    /**
     * Note: each argument is a object that specify the following properties -->
     * inner : the entry object
     * *name : the entry property name
     */

    for (var i = 0, arg, existent, len = arguments.length; i < len; ++i) {
        if (typeof (arg = arguments[i]) === 'object' && (typeof arg.inner === 'object' ? true : arg.inner = {} ))
            /* create new entry/keep existent entry and reserve it in lastObj */
            lastObj = (typeof (existent = lastObj[arg.name]) === 'object' ?
                    lastObj[arg.name] = Object.assign(existent, arg.inner) :
                    lastObj[arg.name] = arg.inner)
    }

    return this
}

然后这是一个基本用法

({}).createEntries({
    name: "val1"
}, {
    name: "val2"
})
/* {
       val1: {
            val2: {
            }
       }
   }
*/

我希望这就是你想要的

答案 2 :(得分:0)

Oriol给了一个很棒的answer,但是由于它的构建方式,他的功能并没有真正用处,因为它返回一个新对象而不是修改 MyObject

因此,为了实际修改 MyObject ,而不是第一个 return ,我们必须做一些其他修改< strong> MyObject ,不会覆盖它。

要做到这一点,必须构建一个扩展 MyObject 的函数:

expand: function (object) {
   for (var key in object) if (!!object[key]) {
      if (key in this) throw new Error("`" + key + "` already exists.");
      else this[key] = object[key];
   }
}

然后,我们所要做的就是在没有第一个 return 语句的情况下使用@Oriol的答案作为 expand() 的参数:< / p>

createEntry: function () {
   this.expand([].reduceRight.call(arguments, function(previous, current) {
      return {[current]: previous};
   }));
}

完整代码:

var MyObject = {
  createEntry: function() {
    this.expand([].reduceRight.call(arguments, function(previous, current) {
      return {
        [current]: previous
      };
    }));
  },
  expand: function(object) {
    for (var key in object)
      if (!!object[key]) {
        if (key in this) throw new Error("`" + key + "` already exists.");
        else this[key] = object[key];
      }
  }
};

MyObject.createEntry("val1", "val2", "val3", "val4");
console.log(MyObject);

感谢大家的帮助!