var allDivs = document.getElementsByTagName('div'); for(var i = 0; i < allDivs.length; i++) { document.body.appendChild(document.createElement('div')); }
Do you see anything wrong in this snippet of code? You would expect it to create one additional div for every div element in the DOM, so it should just double the number of div nodes in the document, right? Well, not really! This is actually an infinite loop. Why? Because the loop's exit condition is never met, as allDivs.length
increases by one with every iteration.
As defined in the DOM standard, HTML collections are "assumed to be live", meaning that they are automatically updated when the underlying document is updated.
So, here is the solution: Store the collection in a local variable, cache the length outside the loop and then use a local variable inside the loop for elements that are accessed more than once. e.g
var coll = document.getElementsByTagName('div'); var len = coll.length; for (var count = 0; count < len; count++) { // if needed cache in here the elements, to work with var el = coll[count]; // do whatever }This will do the magic and solve your problem!
Let's take it one step further. What if you want to touch every element you retrieve from this collection in a way that modifies the live collection. A common example is to replace a class from a collection of elements. e.g
var allDivs = document.getElementsByClassName('class1'); for (var i = 0; i < allDivs.length; i++) { allDivs[i].className = 'class2'; }This doesn't work, since allDivs changes with every iteration of the loop. In this case the best solution to go with is to actually copy the collection into an array and work with the array instead. Something like this:
function toArray(collection) { var result = []; var len = collection.length; for (var i = 0; i < len; i++) { result[i] = collection[i]; } return result; } var allDivs = document.getElementsByClassName('class1'); var ar = toArray(coll); //copies a collection into an array for(var i = 0; i < ar.length; i++) { ar[i].className = 'class2'; }
Now let's look at another neat solution to this problem (unfortunately not supported by all browsers, i.e Internet Explorer 6 and 7). The document.querySelectorAll() method, is provided as a native DOM method. What's cool with it? You can provide a CSS selector as an argument and it will return you a non-live NodeList, an array-like object containing matching nodes, which will not represent the live structure of the document. Let me note here that in W3C's DOM specifications NodeLists are live, but in the case of querySelectorAll(), its explicitly specified that the returned Nodelist is static (not-live)! So, with this method we don't need to be as verbose as we used to be, e.g instead of calling
var elmts = document.getElementsById('menu').getElementsByTagName('a');we can do something like:
var elmts = document.querySelectorAll('#menu a');and of course there's no need to cache/copy variables, in order to access them.
Last but not least...use a library if possible! Avoid dealing with this problem and let the library (e.g YUI, jQuery) do its magic!
References: High Performance JavaScript, Nicholas C. Zakas (http://oreilly.com/catalog/9780596802806)
Another solution for changing all elements with a class name of 'class1' to 'class2' would take advantage of the fact that the HTML collection is live:
ReplyDeletevar allDivs = document.getElementsByClassName('class1');
while (allDivs.length > 0) allDivs[0].className = 'class2';
Great Article
DeleteIEEE Final Year Projects for CSE
IEEE Project Centers in Chennai
To convert NodeList to Array in one line:
ReplyDeletevar divs = document.getElementsByTagName('div');
var array = Array.prototype.slice.call(divs);
@Nikolay, sure thats a nice one liner BUT...it won't work in IE6 (what a surprise, right?) :)
ReplyDelete@Julian well, yeah that would work too, but I don't think working with an HTML collection is actually the best way to go in any case.
ReplyDeleteAccording to tests performed by Zakas' team using arrays instead of collections is 114x faster in IE6, 191x faster in IE7, 79x faster in IE8, ~15x faster in FF3.5, ~8x faster in Chrome3.
Hmmm..yep...no reason to work with HTML collections! :)
Hi, Great.. Tutorial is just awesome..It is really helpful for a newbie like me.. I am a regular follower of your blog. Really very informative post you shared here. Kindly keep blogging. If anyone wants to become a Front end developer learn from Javascript Training in Chennai . or learn thru JavaScript Online Training in India. Nowadays JavaScript has tons of job opportunities on various vertical industry. JavaScript Training in Chennai
ReplyDeleteLovely post... The concepts and the tips given in the post seems to be very much informative and useful.
ReplyDeleteTableau Training in Chennai
Tableau Certification
Oracle DBA Training in Chennai
Advanced Excle Training in Chennai
Graphic Design Courses in Chennai
Unix Training in Chennai
Social Media Marketing Courses in Chennai
Corporate Training in Chennai
Spark Training in Chennai
Pega Training in Chennai
Oracle Training in Chennai
Awesome article! You are providing us very valid information. This is worth reading. Keep sharing more such articles.
ReplyDeleteData Science Course in Chennai
Data Science Course in Coimbatore
Data Science Online Course
Useful Information..!!! Best blog with effective information’s..!!
ReplyDeleteJAVA Training in Chennai
Selenium Training in Chennai
Python Training in Chennai
AWS Training in Chennai
Data Science Course in Chennai
DevOps Training in Chennai
Big data training in chennai
ReplyDeleteBig Data Course in Chennai
Great post. keep sharing such a worthy information
ReplyDeleteAndroid Training in Chennai
Android Training in Bangalore
Great post. keep sharing such a worthy information
ReplyDeletecyber security course in bangalore
cyber security training in chennai
Excellent blog.thanks for sharing such a worthy information....
ReplyDeletebest digital marketing course in chennai
best digital marketing training in chennai
Happy to read the informative blog. Thanks for sharing
ReplyDeletepython coaching centre in chennai
python coaching centre in chennai
Great post. keep sharing such a worthy information.
ReplyDeleteGoogle Ads Training Courses In Chennai
Google Ads Online Course
Happy to read the informative blog. Thanks for sharing
ReplyDeleteIELTS Coaching Center in Chennai
best ielts coaching centre in chennai
This post is so interactive and informative.keep update more information...
ReplyDeleteEthical Hacking Course in Velachery
Ethical Hacking Course in Chennai
Great post. keep sharing such a worthy information.
ReplyDeleteGraphic Design courses in Chennai
Online Graphic Design Course
Graphic Design Courses In Bangalore