2016-05-20 2 views
-1

Пару дней назад я получал удовольствие от некоторых 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... 

В целом, можно определить второй объект в одной функции, можно определить, как много объектов, как вы хотите в вашей второй функции в порядке.

Как я мог достичь этого с помощью моей нынешней структуры?

+3

В чем вопрос? – pvg

+0

Сложно сказать, что именно вы спрашиваете. Пожалуйста, покажите структуру данных до и после, которая показывает желаемый вход и выход. – jfriend00

ответ

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 [{}, "b", "c", "d", "e", "f"] (6) 

Мы можем не петли через объект agruments используя цикл for, поэтому на строке 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, поэтому мы можем вложить объекты в следующий цикл.

Я надеюсь, что это проясняет код

+0

Мне нравится, как вы следовали за общей структурой, которую я давал, но я не совсем понимаю, что происходит в третьей строке, и внутри цикла вы могли бы еще объяснить? –

+0

Спасибо, теперь я понимаю, что происходит. Отличное объяснение! –

1

Итак, вы хотите, чтобы преобразовать значения вложенного объекта?Это может быть сделано путем делать что-то вроде этого:

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] = {}; 

Это создает новый ключ на каждый цикл и присваивает пустой объект к нему. Следующая итерация создает новый ключ (с пустым объектом как значение) внутри вновь созданного объекта из предыдущего цикла. Это продолжается до тех пор, пока не будут назначены все значения массива.

+0

Это очень творческий способ ответить на мой вопрос. Однако, когда вы объясняете, что происходит внутри цикла, вы говорите, что 'a [b] = a [b] [c]' и '{}'. Как это возможно? –

+0

Первая часть перед первым '=' является значением root. Корневая переменная затем создает новый ключ (в данном случае 'c') внутри' a [b] ', поэтому root становится' a [b] [c] '. После последнего '=' вы можете увидеть, что он создает новый пустой объект для 'a [b] [c]', так что следующая итерация может сделать это снова и снова, но затем с 'd'. – Patrick2607