【问题标题】:Automated nested objects自动嵌套对象
【发布时间】:2016-05-20 22:14:37
【问题描述】:

几天前,我正在玩一些 js,当我想到我是否可以自动化对象嵌套的问题时。当然,我还是个新手,所以我还没有走得太远。

但我得到的是这样的:

var a = {};
var stso = ""; storing the second object

function sto(b) { // start the object
    a[b] = {};
    stso = b;
}

function nmo(...objs) { // nesting more object
    console.log(objs[0]);
    if(objs.length) { // checking to see that I have at least one variable before proceding
        for(i = 0; i < objs.length; i++) { // looping through arguments
            a[stso][objs[i]] = {}; // and now I would have to repeat one more more for lever for every argument, meaning, the deeper I want to go into the object, the more nested for loops I have to make.
        }
    }
}

sto("b");
nmo("c");
a.b.c = "Happy ending!";

console.log(a.b.c); // It seems we still dont have a happy ending

// and as a second example

sto("b");
nmo("c", "d", "e", "f", "g");
a.b.c.d.e.f.g = "Another happy ending!";

console.log(a.b.c.d.e.f.g); // Our second happy ending was also unhappy...

总之,您在一个函数中定义第二个对象,您可以按顺序在第二个函数中定义任意数量的对象。

我如何以我目前的结构实现这一目标?

【问题讨论】:

  • 有什么问题?
  • 很难准确说出您的要求。请显示一个前后数据结构,以显示您想要的输入和输出。

标签: javascript nested-loops javascript-objects


【解决方案1】:

如果我理解正确,你可以这样做:

var createNestedObjects = function( obj ) {
    //get all the passed arguments 
    var args = Array.prototype.slice.call(arguments);

    //start with i = 1, as we want to skip obj in the arguments
    for( var i = 1; i < args.length; i++ ) {
        obj = obj[ args[i] ] = obj[ args[i] ] || {};
    }

};

var a = {};
createNestedObjects( a, "b", "c", "d", "e", "f" );
a.b.c.d.e.f = "happy ending";
console.log(a.b.c.d.e.f); //logs "happy ending"

解释行 3

您的要求是将尽可能多的字符串传递给函数,以创建您想要的任何大小的嵌套对象。 但是,如您所见,该函数只有一个参数:obj。 很酷的是,javascript 允许您传递更多参数,并且您仍然可以使用 arguments 对象访问它们。 arguments 对象在所有函数中都可用。 arguments 对象类似于数组,但与它自己的对象不太一样,如果在这种情况下记录它,它将显示:

Arguments [{}, "b", "c", "d", "e", "f"] (6) 

我们不能使用 for 循环遍历 agruments 对象,所以在第 3 行,它首先被转换为一个数组。 arguments object reference


循环内的解释

这一行有两个有趣的部分。 Javascript允许您一次分配多个变量,因为赋值运算符根据其右操作数的值为其左操作数赋值

  var a, b;
  a =  b = 10; //both a and b are set to 10

使用 ||如果左侧的值未定义,则此处使用运算符设置默认值(在本例中为 {} )。例如,设置默认值也很方便

function setDelay ( delay ){

    delay = delay || 60
    return delay

}

setDelay(  ) //no parameter is passed, delay is set to 60 
setDelay( 120 ) 120 is passed and delay is set to 120

在这种情况下是行

obj = obj[ args[i] ] = obj[ args[i] ] || {};

可以改写为:

var name = args[i];    // first loop args[i] is "b"    
if(!obj[name]){        // a.b does not exist       
    obj[name] = {};    // a.b is set to {}      
}
obj = obj[name];       // a is set to a.b 

它检查是否已经存在具有该名称的对象,如果没有,则创建并设置为 obj,以便我们可以在下一个循环中嵌套对象。

我希望这可以澄清代码

【讨论】:

  • 我喜欢你遵循我给出的整体结构的方式,但我并不完全理解第三行和循环内部发生了什么,你能进一步解释一下吗?
  • 谢谢,现在我明白发生了什么。很好的解释!
【解决方案2】:

那么,您想将值转换为嵌套对象吗?这可以通过执行以下操作来完成:

let values = ['b', 'c', 'd', 'e', 'f', 'g'];
let a = {};
// Every time we loop, we change the root
let root = a;

for (let value of values) {
  // Set root to the value of the array and assign a new object
  root = root[value] = {};
}
// Set the string
a.b.c.d.e.f.g = "Happy ending!";

console.log(a.b.c.d.e.f.g);
console.log(a);

它基本上是在循环内完成的:

a = a[b] = {};
a[b] = a[b][c] = {};
a[b][c] = a[b][c][d] = {};
a[b][c][d] = a[b][c][d][e] = {};
a[b][c][d][e] = a[b][c][d][e][f] = {};
a[b][c][d][e][f] = a[b][c][d][e][f][g] = {};

它在每个循环中创建一个新键并为其分配一个空对象。下一次迭代在前一个循环中新创建的对象内创建一个新键(以一个空对象作为值)。这种情况一直持续到数组的所有值都已分配完毕。

【讨论】:

  • 这是一个非常有创意的方式来回答我的问题。但是,当您解释循环内发生的事情时,您会说a[b] = a[b][c]{}。这怎么可能?
  • 第一个=之前的第一部分是root的值。然后根变量在a[b] 内创建一个新键(在本例中为c),因此根变为a[b][c]。在最后一个 = 之后,您可以看到它为 a[b][c] 创建了一个新的空对象,以便下一次迭代可以再次执行此操作,但随后使用 d
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-09-10
  • 2012-04-10
  • 1970-01-01
  • 1970-01-01
  • 2019-11-22
  • 1970-01-01
相关资源
最近更新 更多