1

I have a for loop which should loop through an object. But this object can have many other object levels inside it. How can I make a function that should make for loops inside for loops as many levels deeps as I want?

Something like this, where the lvl variable would be the number of levels it should dive in:

var lvl = 5;

for (var i = 0; i < groups.length; i++) {
    var groups = groups[i];

    for (var i = 0; i < groups.length; i++) {
        var groups = groups[i];

        for (var i = 0; i < groups.length; i++) {
            var groups = groups[i];

        }
    }
}

For example, if I have the following object tree:

var foo = {
  child: {
    grand:{
      greatgrand: {
      }
    }
  }
}

How can I console log all the object tree names just by diving to a specific level in the foo object?

dive(2); // would dive to level two (grand)

// would return the following in the console
child
grand
gespinha
  • 7,968
  • 16
  • 57
  • 91
  • 5
    You should look into recursive functions – Jan Sep 11 '15 at 23:49
  • You need separate variables for each nested `for` loop so one loop is not overwriting the variables from the others or you can make a function to do the looping and call it recursively. – jfriend00 Sep 11 '15 at 23:52
  • Do you have an array or an object? – epascarello Sep 11 '15 at 23:56
  • Choose a *different* variable name for each loop. JavaScript *only* has a function (and global) variable scope so every `i` (and `groups`) represents the *same* variable and the multiple occurrences of `var` is irrelevant. Search for "variable hoisting" for more details. (With that aside, recursion is pretty natural for "N-levels" although using a stack would be another solution.) – user2864740 Sep 12 '15 at 00:02
  • Wrt. variable scopes: http://stackoverflow.com/questions/500431/what-is-the-scope-of-variables-in-javascript , http://stackoverflow.com/questions/30575151/variable-hoisting-in-javascript – user2864740 Sep 12 '15 at 00:03

2 Answers2

2

A recursive function--a function that calls itself--is the way to go. You'd want something like this:

/* pseudo-code; this will not run */
function processThing(thing) {
  if (thing is an object) {
    // process all of thing's properties
    for (property in thing) {
      processThing(property);
    }
  }
  else {
    // process thing as a value
  }
}
Brandon Gano
  • 6,430
  • 1
  • 25
  • 25
2

Here you go. I have coded a recursive function which will iterate an object graph. You can provide a depth argument to the traverse function.

A JSFiddle is here. Please check the developer tools console for output.
A fiddle with indentation added is here

var obj = {
firstName: "John",
lastName: "Doe",
address1A: {
    street: "120 Washington St",
    city: "Mountain View",
    state: "CA",
    address2A: {
        street: "100 Washington st",
        city: "Mountain View",
        state: "CA",
        address3A: {
            street: "150 Washington st",
            city: "Mountain View",
            state: "CA",
            address4A: {
                street: "150 Washington st",
                city: "Mountain View",
                state: "CA",
            }
        }
    }
},
address1B: {
    street: "120 Washington St",
    city: "Mountain View",
    state: "CA",
    address2B: {
        street: "100 Washington st",
        city: "Mountain View",
        state: "CA",
        address3B: {
            street: "150 Washington st",
            city: "Mountain View",
            state: "CA",
            address4B: {
                street: "150 Washington st",
                city: "Mountain View",
                state: "CA",
            }
        }
    }
}
};

function traverse(initObj, depth) {
     depthTraversal(initObj, depth, 1);
}

function depthTraversal(objArg, depthArg, counterArg) {
    //create a closure for remembering loop variables
    return (function (myObj, myDepth, counter) {
        //console.log(myDepth + " - " + counter);
        if (myDepth < counter) {
          return;
        }
       //console.log(myObj);
       for (var prop in myObj) {
          //console.log(prop + " :" + typeof (myObj[prop]));
          if (myObj.hasOwnProperty(prop)) {
             if (typeof (myObj[prop]) === "object") {
                console.log(prop);
                depthTraversal(myObj[prop], myDepth, counter + 1);
             }
          }
      }
}(objArg, depthArg, counterArg)); //IIFE
};


traverse(obj, 4);
santon
  • 1,654
  • 16
  • 26