skip to Main Content

HTML :

<html>
   <body>
       <div id="a">
       </div>
   </body>
</html>

Above is my simple html given and i wrote a function to add a children div in each div.

 function appendChildren() {
       var allDivs = document.getElementsByTagName("div");
       console.log(allDivs) // [div#a, a: div#a]
       console.log(allDivs.length) // 1
       for (let i = 0; i < allDivs.length; i++) {
           let newDiv = document.createElement("div");
           allDivs[i].appendChild(newDiv);
       }
   }
   appendChildren();

I was expecting above function will add div in each div but it not working as expected after calling appendChildren() it went to infinite loop and keep load. Help me out to understand how and why its happen it will help me and others who learning javascript. Thanks!!!

2

Answers


  1. This returns a "live collection":

    var allDivs = document.getElementsByTagName("div");
    

    What that means is that, as the DOM is updated, so is this collection. Coincidentally, this is a collection of all <div> elements. And you’re adding a <div> element:

    let newDiv = document.createElement("div");
    allDivs[i].appendChild(newDiv);
    

    So every iteration of the loop adds the next element for the loop. Infinitely.

    You can observe the difference by simply wrapping the collection in Array.from() to create a copy of the collection as an array:

    var allDivs = Array.from(document.getElementsByTagName("div"));
    

    Since it’s a copy, it’s no longer a "live" collection.

    For a DOM method which doesn’t return a "live" collection, you can also use querySelectorAll. For example:

    var allDivs = document.querySelectorAll("div");
    
    Login or Signup to reply.
  2. Instead of updating the live collection you get with getElementsBy…, get the top level using querySelectorAll and add to that (unless you want more than one level of nesting)

    const allTopLevelDivs = document.querySelectorAll("body > div");
    const appendChildren = () => {
      allTopLevelDivs.forEach(div => {
        let newDiv = document.createElement("div");
        newDiv.textContent = `Child of ${div.id}`;
        div.appendChild(newDiv);
      });
    }
    appendChildren();
    <div id="a">A</div>
    <div id="b">B</div>
    <div id="c">C</div>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search