Search code examples
javascriptobjectpropertiesnestedfor-in-loop

How to get the right property of a nested object property in a for...in?


Given the following snippet:

let PARENT = {
  CHILD_1: {
    no: '1',
    page: 3,
    toString: function(){ return this.no; } },
  CHILD_2: {
    no: '2',
    page: 4,
    toString: function(){ return this.no; } },
}
console.log( JSON.stringify(PARENT, null, 1) )

for ( let c in PARENT ) {
  // c is a CHILD_n object here, right?

  console.log(c)  // why 'CHILD_n' instead of 'no' from toString()?
  console.log(c.page)  // why undefined instead of 'page'?
}

I don't get the expected results:

  1. Why is c resolved to the CHILD_n property's name rather than the value returned by toString()?
  2. Why is c.page undefined? 1. Isn't c a CHILD_n object with its properties available?
  3. How to get the expected values?

Solution

  • As mentioned in the comments, for... in loops though the keys; i.e. the strings 'CHILD_1' and 'CHILD_2' as opposed to the objects.

    for... of iterates through the values, however, you can't directly iterate an object, as objects are not iterable. for (value of {}) {} will throw an error.

    Instead, you'll have to obtain the iterable list of values via e.g. Object.values prior to iterating using for... of.

    Lastly, toString is not automatically invoked by console.log, so you'll have to call it explicitly.

    let PARENT = {
      CHILD_1: {
        no: '1',
        page: 3,
        toString: function(){ return this.no; } },
      CHILD_2: {
        no: '2',
        page: 4,
        toString: function(){ return this.no; } },
    };
    
    for ( let c of Object.values(PARENT) ) {
      console.log(c);
      console.log(c.toString());
      console.log(c.page);
    }