jQuery.fn.each vs. jQuery.fn.quickEach

JavaScript performance comparison

Revision 48 of this test case created by Andy Harman and last updated

Info

Fast alternative to $.fn.each(func). Most usage of fn.each immediately evaluates $(this) - which is really expensive. This version changes this so that it already points to a single-element jQuery object.

Notes:

My previous implementation (48) was bobbins because modern JS engines use short-circuiting to avoid doing work ... and there was a bug that you could drive a bus through.

Preparation code

<script src="//ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js">
</script>
<script>
  var a = $('<div/>').append(Array(100).join('<a></a>')).children();
 
  // Modified quickEach plugin
  jQuery.fn.quickerEach = (function() {
    var jq = jQuery([1]);
    return function(c) {
      var i = -1, el;
      try {
        while (el = jq[0] = this[++i] && c.call(jq, i, el) !== false);
      } catch (e) {
        jq[0] = 1;
        throw e;
      }
      jq[0] = 1;
      return this;
    };
  }());

  // James Padolsey's quickEach plugin
  jQuery.fn.quickEach = (function() {
    var jq = jQuery([1]);
    return function(c) {
      var i = -1, el, len = this.length;
      try {
        while (++i < len && (el = jq[0] = this[i]) && c.call(jq, i, el) !== false);
      } catch (e) {
        delete jq[0];
        throw e;
      }
      delete jq[0];
      return this;
    };
  }());
</script>

Preparation code output

Test runner

Warning! For accurate results, please disable Firebug before running the tests. (Why?)

Java applet disabled.

Testing in unknown unknown
Test Ops/sec
.each()
var count = 0;
a.each(function() {
  $(this).addClass("fred");
});
pending…
.quickEach()
a.quickEach(function() {
  this.addClass("fred"); // jQuery object
});
pending…
.quickerEach()
a.quickerEach(function() {
  this.addClass("fred"); // jQuery object
});
pending…
For loop
//Note that this may be more suitable for your needs.
var jq = jQuery([1]);
for (var i = 0, len = a.length; i < len; i++) {
  jq[0] = a[i];
  jq.addClass("fred"); // jQuery object
}
//For fastest performance - avoid jQuery and go direct to the DOM.
 
pending…

Compare results of other browsers

Revisions

You can edit these tests or add even more tests to this page by appending /edit to the URL. Here’s a list of current revisions for this page:

1 comment

Andy Harman (revision owner) commented :

This test case contained a major bug. The quickerEach implementation depended on the following code:

while (el = jq[0] = this[++i] && c.call(jq, i, el !== false);

I forgot that operator precedence would cause this to be evaluated as (note the added-brackets):

while (el = jq[0] = (this[++i] && c.call(jq, i, el !== false) );

So the addClass method was chewing on a boolean rather than a DOM element.

Add a comment