Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Most efficient way to iterate over all DOM elements

Unfortunately I need to iterate over all the DOM elements of a page and I'm wondering what the most efficient technique is. I could probably benchmark these myself and might if I have the time but I'm hoping someone has already experienced this or has some options I hadn't considered.

Currently I'm using jQuery and doing this:

$('body *').each(function(){                                                                                                                                 var $this = $(this);                                                                                                                                     // do stuff                                                                                                                                          }); 

While it works, It seems to cause some lag on the client. It could also be tweaked with a more specific jQuery context like $('body', '*'). It occurred to me that native Javascript is usually faster than jQuery and I found this:

var items = document.getElementsByTagName("*"); for (var i = 0; i < items.length; i++) {     // do stuff } 

I'm assuming the native option is faster. Wondering if there are other options I hadn't considered. Maybe a recursive option that iterates over child nodes in parallel.

like image 825
kevzettler Avatar asked Jan 05 '12 17:01

kevzettler


People also ask

How do I loop through all DOM elements?

To loop through all DOM elements: Use the getElementsByTagName() method to get an HTMLCollection containing all DOM elements.

Which methods are used to get more than one elements from the DOM?

Accessing Elements by Class The class attribute is used to access one or more specific elements in the DOM. You can get all the elements with a given class name with the getElementsByClassName() method. Now we want to access more than one element, and in our example we have two elements with a demo class.

How many DOM nodes are too many?

By Brandon Devnich| January 8, 2019. As covered by Google, an excessive DOM (Document Object Model AKA web page) can harm your web page performance. It is recommended that your web page have no more than 900 elements, be no more than 32 nested levels deep, or have any parent node that has more than 60 child nodes.


2 Answers

The Vanilla Javascript way you posted is the fastest. It will be faster than the jQuery solution you posted (See my comment on the question). If you're not removing or adding anything to the DOM in your loop and order of traversal doesn't matter, you can also speed it up ever so slightly by iterating in reverse:

var items = startElem.getElementsByTagName("*"); for (var i = items.length; i--;) {     //do stuff } 

Edit: check this benchmark to see how much time you can save by using the native code: http://jsben.ch/#/Ro9H6

like image 149
Paul Avatar answered Sep 28 '22 09:09

Paul


UPDATE:

Don't use $('body *') to iterate over the elements. It will be much quicker to use $('*') if you go for the JQuery method (see comments for details).


Plain ol' JavaScript is much faster, relatively speaking.

Using a test fiddle, I get about 30ms to process 13000 elements with JQuery, and 8ms to process 23000 elements using JavaScript (both tested on Chrome):

JQuery:      433  elements/ms JavaScript:  2875 elements/ms  Difference:  664% in favor of plain ol' JavaScript 

Note: Unless you have an incredibly large amount of elements on your page, this isn't going to make much of a difference. Also, you probably should time the logic in your loop, as that might be the limiting factor in all this.

Update:

Here is the updated results when considering much more elements (about 6500 per loop), I get about 648000 elements in 1500ms with JQuery, and 658000 elements in 170ms with JavaScript. (both tested on Chrome):

JQuery:      432  elements/ms JavaScript:  3870 elements/ms  Difference:  895% in favor of plain ol' JavaScript 

Looks like JavaScript sped up while JQuery stayed about the same.

like image 45
Briguy37 Avatar answered Sep 28 '22 09:09

Briguy37