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!

3
  • 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 Commented Oct 11, 2016 at 8:15
  • Why is it not true? can you please explain a little bit further? Commented Oct 11, 2016 at 8: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 Commented Oct 11, 2016 at 8:24

2 Answers 2

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);
};
Sign up to request clarification or add additional context in comments.

5 Comments

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.
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.
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 has interesting insights about it.
haha. Now I am laughing at myself. Now I understand. Thank you @damienc for the link.
See this bin, it highlights this mechanism.
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.

1 Comment

treeList contains the root elements of the hierarchy, which in turn contain children elements in their children array.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.