4

I have been searching through the internet and cannot find the right word to search so I end up here asking again to all of you seniors in Javascript. The code below is taken from the answer on these question I really don't understand how the method or function work.

var list = [{id: 1,title: 'home',parent: null},{id: 2,title: 'about',parent: null},{id: 3,title: 'team',parent: 2},{id: 4,title: 'company',parent: 2} ];
function treeify(list) {
     var treeList = [];
     var lookup = {};
     list.forEach(function(obj) {
          obj['children'] = [];
          lookup[obj['id']] = obj;
     });
     console.log(lookup); // [problem number 1]

     list.forEach(function(obj) {
          if (obj['parent'] != null) {
               lookup[obj['parent']]['children'].push(obj);
          } else {
               treeList.push(obj);
          }
     });

     console.log(treeList); // [problem number 2]
};

treeify(list);

On problem number 1:

It resulted an object that had already a children on each parent which is supposedly I think that, parent should have an empty array children at that moment. How does it work? Please enlightened me.

On problem number 2

treeList already formed the hierarchy tree. How it happen? it didn't even push the lookup variable to the treeList variable? It only pushes the obj with a parent that is equal to null (which is the root parent).

Hoping for your answer. If you know any blog, article and etc. that may help me understand javascript please don't hesitate to add the link in your answer. Many Thank you!

Community
  • 1
  • 1
Abz Rockers
  • 338
  • 1
  • 11
  • 1
    You problem #1 is that what you see in console.log is not a true picture of the state of lookup at that point in time ... try `console.log(JSON.parse(JSON.stringify(lookup)));` to see a "snapshot" of lookup at that point – Jaromanda X Oct 11 '16 at 08:15
  • Why is it not true? can you please explain a little bit further? – Abz Rockers Oct 11 '16 at 08:18
  • 1
    Because console.log outputs the object, you expand that object, it shows it's CURRENT state, not the state at which the object was logged – Jaromanda X Oct 11 '16 at 08:24

2 Answers2

1
var list = [
     {id: 1,title: 'home',parent: null},
     {id: 2,title: 'about',parent: null},
     {id: 3,title: 'team',parent: 2},
     {id: 4,title: 'company',parent: 2} 
];

treeify(list);


function treeify(list) {

     var treeList = []; //local array
     var lookup = {}; //local object

     // iterate over each element in list array
     list.forEach(function(obj) {

          // add a children property to each element in the array
          // in this case the children property is an array
          obj['children'] = [];

          // obj['id'] returns 1,2,3,4
          // lookup is an object so we use the id of each element in the list array as a key
          // first iteration adds key : 1 and value {id:1, title: 'home', parent: null, children: [] }
          // second iteration adds key : 2 and value {id:2, title: 'about', parent: null, children: [] }
          // ...
          lookup[obj['id']] = obj;
     });

     /*
          console.log(lookup) should output
          {
               1: {id: 1,title: 'home', parent: null, children: []},
               2: {id: 2,title: 'about', parent: null, children: []},
               3: {id: 3,title: 'team', parent: 2, children: []},
               4: {id: 4,title: 'company', parent: 2, children: []} 
          }

          however, if you run the code the lookup object gets modifyed in 
          the lines below (lookup[obj['parent']]['children'].push(obj);),
          therefore, some items in the lookup object will have children elements in its child array
     */
     console.log(lookup); // [problem number 1]

     list.forEach(function(obj) {
          if (obj['parent'] != null) {
               // this line modifyes the lookup object at runtime
               // obj has a parent, so we add it to the corresponding parents children array using the id
               lookup[obj['parent']]['children'].push(obj);
          } else {
               //only adds an element to the treelist array if its a parent element
               treeList.push(obj);
          }
     });

     console.log(treeList);
};
Ivan Bacher
  • 5,855
  • 9
  • 36
  • 56
  • 1
    The `treeList` objects are references to the one from `lookup`. To illustrate this, we can add a `lookup['4'].title = 'random title';` after the last `forEach` loop and see the `treeList` object get modified. – dashdashzako Oct 11 '16 at 08:28
  • Sorry I am still noob on javascript. So you mean that is how you do reference in javascript? specifically on this line code lookup[obj['id']] = obj ? I thought it's just copying the value of the obj. – Abz Rockers Oct 11 '16 at 08:42
  • 2
    Actually I think this is why you didn't understand the code in the first place. The objects are not copied, just referenced. [This question](http://stackoverflow.com/questions/6605640/javascript-by-reference-vs-by-value) has interesting insights about it. – dashdashzako Oct 11 '16 at 08:49
  • haha. Now I am laughing at myself. Now I understand. Thank you @damienc for the link. – Abz Rockers Oct 11 '16 at 08:55
  • 2
    See [this bin](https://jsbin.com/sujuheduki/edit?js,console), it highlights this mechanism. – dashdashzako Oct 11 '16 at 08:59
1

Problem 1:
You are right with your assumption, but the problem is that console.log is logging a reference. Because the lookup object gets changed later on you see these changes. read more

function treeify(list) {
    var treeList = [];
    var lookup = {};
    list.forEach(function(obj) {
        obj['children'] = [];
        lookup[obj['id']] = obj;
    });
    console.log(lookup); // Now you're right
};

Problem 2:
All objects in lookup are referenced to list.

lookup[obj['id']] = obj;

Here the childrens get changed.

lookup[obj['parent']]['children'].push(obj);

In treeList are also the same references.

Community
  • 1
  • 1
Huntro
  • 322
  • 1
  • 3
  • 16
  • ```treeList``` contains the root elements of the hierarchy, which in turn contain children elements in their children array. – Ivan Bacher Oct 11 '16 at 08:31