$().each vs $.each vs for loop in jQuery?

33,384

Solution 1

Your test is too heavy to really determine the actual difference between the three looping options.

If you want to test looping, then you need to do your best to remove as much non-related work from the test as possible.

As it stands, your test includes:

  • DOM selection
  • DOM traversal
  • element mutation

All of those are quite expensive operations compared to the loops themselves. When removing the extra stuff, the difference between the loops is much more visible.

http://jsperf.com/asdasda223/4

In both Firefox and Chrome, the for loop is well over 100x faster than the others.

enter image description here

Solution 2

Well

  • $.each() is a jQuery function being executed which will be used to iterate over your list, so the overhead should be the jQuery function as well as the overhead of calling for that function for every item in the list. In this case
  • $(thing).each() The idea behind this is that the $(thing) makes an jQuery instance and then you iterate over this instance (.each acts on that instance). In your case, because the instance you called it with is already a jQuery object, the overhead is minimal (are you an instance, oh yes you are).
  • for() In this case there is no overhead at all, except looking up the length of the list on each iteration.

Consider doing:

var l = g.length;
for (var i=0;i<l;i++) {
    // code;
}

Depending on your HTML most of the time could very well be in the Sizzle Jquery parser finding your selector in the document.

Also note, I don't think your selector is the best, unless things have changed significantly recently jQuery selectors are evaluated right to left, consider limiting the scope of the selector by doing a .find() on everything beneath the first tag referenced by id as it will then be searching only a subset of the document.

Share:
33,384
Royi Namir
Author by

Royi Namir

Updated on June 02, 2020

Comments

  • Royi Namir
    Royi Namir about 4 years

    I Can't understand why it is happening.

    I read here that :

    The first $.each constitutes a single function call to start the iterator.

    The second $(foo.vals).each makes three function calls to start the iterator.

    • The first is to the $() which produces a new jQuery wrapper set (Not sure how many other function calls are made during this process).
    • Then the call to $().each.
    • And finally it makes the internal call to jQuery.each to start the iterator.

    In your example, the difference would be negligible to say the least. However, in a nested use scenario, you might find performance becoming an issue.

    Finally, Cody Lindley in jQuery Enlightenment does not recommend using $.each for iterations greater than 1000 because of the function calls involved. Use a normal for( var i = 0... loop.

    So I tested it with this jsperf :

    (task : find Tr's who has checked checkbox inside of them , and color that tr.)

    This is the jsbin

    But look at jsperf

    against all expectations , the opposite is the true. ( chrome and FF and IE)

    enter image description here

    The one who uses $().each ( which calls three methods is the fastest and etc..

    What is going on here?

  • Royi Namir
    Royi Namir over 11 years
    If me you and him has both work to do then it should be proportional to each.what does it matter how much those function has to do ? as long they all do the same....
  • the system
    the system over 11 years
    @RoyiNamir: Because you're no longer testing the loop, but everything else as well. I'm just saying that the actual difference between the loops is entirely obscured by the work that is being done. If you don't care about the difference between the loops, then don't bother testing it. If you do, then you need to test it properly.
  • Royi Namir
    Royi Namir over 11 years
    Reading again your comment. I believe you are right. I mixed up the elements selector engine which could be different in each browser. +1
  • Salman A
    Salman A over 11 years
    If you pre-calculate g.length the loop will be even faster.
  • Christoph
    Christoph over 11 years
    ah, and of course +1 for the answer for introducing how to test properly!
  • Royi Namir
    Royi Namir over 11 years
    @Christoph how the hell the opposite for is faster ? does it every time calculate the g ? (without saving g)
  • Liviu T.
    Liviu T. over 11 years
    @thesystem shouldn't the test of for loop include the creation of the parameters that are passed to the function in the $.each and $().each? I feel like the results are misleading. An empty for loop doesn't show the actual costs of creating a jQuery object for each element in the array
  • the system
    the system over 11 years
    @LiviuT. None of them show the cost of creating a jQuery object for each element. jQuery doesn't automatically do that.
  • the system
    the system over 11 years
    @RoyiNamir: There were two changes to that test... The reverse iteration, and the cached .length. The cached .length would likely be more responsible for the improvement. The reverse iteration... not so much. There's a different reverse iteration that's used that can be beneficial. var i = j.length; while (i--) {...} Now we've eliminated the comparison operator, and the current value of i is just tested for truthiness.
  • the system
    the system over 11 years
    @RoyiNamir: I updated the test to include at least a little work. I have a feeling that the JS engine was optimizing the for loop away entirely. This one increments a counter in the loop, and uses the result to generate a random number. jsperf.com/asdasda223/8 The for loop is still much faster, but not as fast as before. I also added a .forEach() test.
  • the system
    the system over 11 years
    @RoyiNamir: With today's JS engines that compile code, it more often comes down to whatever optimizations have been made under the hood. Historically it's had a small performance benefit, but it's certainly not a guarantee.
  • Royi Namir
    Royi Namir over 11 years
    @thesystem can you please explain why the reverse for loop is faster ?
  • the system
    the system over 11 years
    Your most recent test doesn't have a reverse for loop, but it does have a forward for loop with the .length cached. But to be honest, no I can't explain it. Again, it comes down to the under-the-hood optimizations provided by the underlying implementation. We would need to examine the source code for Google V8 to really understand why.
  • Royi Namir
    Royi Namir over 11 years
    @thesystem the last test in jsperf.com/asdasda223/9 is not reversed for loop ?
  • scott.korin
    scott.korin over 10 years
    Just for the heck of it, I also added a test with caching the array length in the for loop: jsperf.com/asdasda223/38
  • Richard
    Richard over 10 years
    To avoid looking up the length on every iteration (which usually doesn't change for the duration of the loop) you can do this: for (var i=0,len=myArray.length; i<len; i+=1) {}
  • Thomas
    Thomas almost 9 years
    -1 Because empty loops are an unrealistic test. No developer cares if an empty for loop is faster than an empty .each() loop. What matters to a developer is which loop is faster when performing work. The question is about why real world performance doesn't match empty benchmarks. Answering that it's because his loops aren't empty is a tautology.
  • Vasil Popov
    Vasil Popov over 8 years
    -1 Because the case is asked with ENUMERABLE type of data! The test is not about which of the the different types of loops is faster, as atomic operations. It is about the performance over the specific case with this data. And yes, this includes the operations over the data! And yes, the each is faster because enumerates a LIST, not an ARRAY!