Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

$.each() vs for() loop - and performance

These are mainly just some things I've been wondering, maybe someone can give me a little more insight on them, i'll share what i've noticed so far as well!

First thing i've been wondering... is there any difference good or reason to use:

$('element').each(function (i, el) { });

-- versus --

$.each($('element'), function (i, el) { });

Looking at the jQuery docs I can't see any rhyme or reason for one or the other (maybe you know an instance or additional things one can do over the other.

But more importantly I'm concerned with speed here

// As opposed to $.each() looping through a jQuery object // -- 8x faster  for (var i = 0, $('.whatever').length; i < len; i++) {     $('.whatever')[i] // do stuff } 

If you check out this jsFiddle DEMO here, you'll see the difference in speed is basically equivalent with either of them, but more importantly I feel like I should always be using for() loops...

I was just unit testing (looping through each of 5 different scenario functions, 50,000 times), simply looping through a bunch of list items, and setting a data-newAttr, nothing special.


QUESTION :: I guess my biggest question is, why not always use for loops while iterating through an object?? Is there even a point to using $.each()? Do you always use for() loops even when going through jQuery objects?

jsFiddle DEMO here

Function type:                  Execution Time: _testArea.each() + $(this)               1947   <-- using $(this) slows it down tremendously $.each()         + $(this)               1940 _testArea.each() + el(plain JS)           458   <-- using the Element speeds things up $.each()         + el(plain JS)           452 for() loop       + plainJS[0] iteration   236   <-- over 8x faster 

Just my 2cents. :)

like image 957
Mark Pieszak - Trilon.io Avatar asked Aug 09 '12 16:08

Mark Pieszak - Trilon.io


People also ask

Which is faster each or for loop?

The forloop is faster than the foreach loop if the array must only be accessed once per iteration.

Which is faster for loop or forEach JS?

forEach is almost the same as for or for..of , only slower. There's not much performance difference between the two loops, and you can use whatever better fit's the algorithm. Unlike in AssemblyScript, micro-optimizations of the for loop don't make sense for arrays in JavaScript.

Are forEach loops slower?

Not only is it significantly slower in general, but foreach becomes significantly slower than accessing by index. Having said that, I would still almost always prefer foreach to a for loop where it makes the code simpler - because readability is almost always important, whereas micro-optimisation rarely is.


2 Answers

One thing that .each() allows you to do that can't be done with a for loop is chaining.

$('.rows').each(function(i, el) {     // do something with ALL the rows }).filter('.even').each(function(i, el) {     // do something with the even rows }); 

I played around with your JSFiddle to see how chaining would influence performance in cases where you have to loop through subsets of the original set of matched elements.

The result wasn't all that unexpected, although I think the overhead of end() was exaggerated here because of the combination of few elements and many loops. Other than that: plain JS loops are still slightly faster, but whether that weighs up to the added readability of .each() (and chaining) is debatable.

like image 69
Peter-Paul van Gemerden Avatar answered Sep 30 '22 17:09

Peter-Paul van Gemerden


One thing you do get with .each() is automatic local scoping (because you are invoking an anonymous function for every object), which in turn means if you are creating even more anonymous functions/closures/event handlers/whatever on every iteration, you never have to worry about your handlers sharing a variable. That is, JavaScript doesn't act like other languages when it comes to local scopes, but because you can declare a variable anywhere, it can fool you sometimes.

In other words, this is wrong:

var idx,el; for (idx = 0; idx <someObjectArray.length; idx++){    el = someObjectArray[idx]    el.someEventHandler(function(){          alert( "this is element " + idx);    });  } 

Whenever any of those objects invoke their "someEvent" after this loop (please note that this is made up), the alert is always going to say whatever was last assigned to idx, which should be (as of the time invoked) someObjectArray.length;

To make sure you save the proper index, you have to declare a local scope, create a variable and assign to that variable for use.

var idx,el; for (idx = 0; idx <someObjectArray.length; idx++){    el = someObjectArray[idx];    (function(){        var localidx = idx;        el.someEventHandler(function(){              alert( "this is element " + localidx);        });     })(); } 

As you can see, that's as ugly as hell, but it should work. Each event handler gets its own copy of localidx

Now compare that to .each()

$(someObjectArray).each(function (idx, el) {     el.someEventHandler(function(){          alert( "this is element " + idx);    });  }); 

A lot simpler, isn't it?

like image 26
JayC Avatar answered Sep 30 '22 16:09

JayC