The most efficient way to iterate over all DOM elements?

Unfortunately, I need to iterate over all the elements of the DOM page, and I wonder what the most efficient technique is. I could probably compare them and, if I have the time, but I hope that someone has already experienced this or has some options that I have not considered.

I am currently using jQuery and doing this:

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

While it works, it seems to cause some lagging behind the client. It can also be modified using a more specific jQuery context such as $('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 guess the native option is faster. Wonder if there are other options that I have not considered. Maybe a recursive variant that repeats over child nodes in parallel.

+55
performance optimization javascript jquery dom
Jan 05 2018-12-12T00:
source share
5 answers

The vanilla Javascript method you posted is the fastest. This will be faster than the jQuery solution you posted (see my comment on the question). If you don't delete or add anything to the DOM in your loop, and the traversal order doesn't matter, you can also speed it up a bit, iterating in the opposite direction:

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

Edit : check this metric to see how much time you can save using your own code: http://jsben.ch/#/Ro9H6

+33
Jan 05 2018-12-12T00:
source share

UPDATE:

Do not use $('body *') to iterate over elements. When using the jQuery method, it is much easier to use $('*') (see comments for more details).




Plain ol 'JavaScript is much faster, relatively speaking.

Using test fiddle , I get about 30 ms to process 13,000 elements using jQuery and 8 ms to process 23,000 elements using JavaScript (both tested on Chrome):

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

Note. If your page does not have an incredibly large number of elements, this will not matter much. Also, you probably need time logic in your loop, as this can be a limiting factor in all of this.

Update:

Here are the updated results when considering a much larger number of elements (about 6500 per cycle), I get about 648000 elements in 1500 ms using JQuery and 658000 elements in 170 ms with JavaScript. (both tested in Chrome):

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

It seems that JavaScript has accelerated, and jQuery has remained roughly the same.

+16
Jan 05 '12 at 18:53
source share

This is not a good idea, but this should work:

 function walkDOM(main) { var arr = []; var loop = function(main) { do { arr.push(main); if(main.hasChildNodes()) loop(main.firstChild); } while (main = main.nextSibling); } loop(main); return arr; } walkDOM(document.body); 

Not including text fields:

 function walkDOM(main) { var arr = []; var loop = function(main) { do { if(main.nodeType == 1) arr.push(main); if(main.hasChildNodes()) loop(main.firstChild); } while (main = main.nextSibling); } loop(main); return arr; } 

Edited by!

+11
Jan 05 2018-12-12T00:
source share

The fastest way looks like document.all (note that this is a property, not a method).

I changed Brigi's response script to write them instead of jQuery, and it is consistently faster (than document.getElementsByTagName('*') ).

The violin .

+6
May 16 '13 at 14:27
source share

This is a solution to the problem, as described in the comments (although not on the current issue). I think it would be much faster to use elementFromPoint to check the area in which you want to place a fixed position element, and only worry about the elements in that area. Example:

http://jsfiddle.net/pQgwE/4/

Basically, just set the minimum possible size of the element you are looking for and scan the entire area that your new fixed position element wants to occupy. Create a list of unique elements found there, and only worry about checking the style of these elements.

Note that this method assumes that the item you are looking for has the highest z index (which seems like a reasonable assumption for a fixed position). If this is not enough, then this can be adjusted to hide (or assign a minimum z-index) to each element after it is detected and check the point again until nothing is found (if necessary), and then restore them later. This must happen so quickly as to be inconspicuous.

HTML:

 <div style="position:fixed; left: 10px; top: 10px; background-color: #000000; color: #FF0000;">I Am Fixed</div> <div id="floater">OccupyJSFiddle!<br>for two lines</div> 

JS:

 var w = $(window).width(), h=$(window).height(), minWidth=10, minHeight=10, x,y; var newFloat = $('#floater'), maxHeight = newFloat.height(), el, uniqueEls=[], i; for (x=0;x<w;x+=minWidth) { for (y=0;y<h&& y<maxHeight;y+=minHeight) { el = document.elementFromPoint(x,y); if (el && $.inArray(el,uniqueEls)<0) { uniqueEls.push(el); } } } // just for the fiddle so you can see the position of the elements // before anything done // alert("click OK to move the floater into position."); for (i=0;i<uniqueEls.length;i++) { el = $(uniqueEls[i]); if (el.css("position")==="fixed") { el.css("top",maxHeight+1); } } newFloat.css({'position': 'fixed', 'top': 0, 'left': 0}); 
+3
Jan 05 2018-12-12T00:
source share



All Articles