jQuery.fn.each vs. jQuery.fn.quickEach (v48)

Revision 48 of this benchmark created by Andy Harman on


Description

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:

  • The callback function is normally much slower than each so the benefit of quickerEach often isn't dramatic. A simple for-loop may be more suitable.

  • Your callback function MUST NOT call quickEach (i.e. nesting).

  • Your callback function MUST NOT store the value of this to a closure variable (I accidentally did once - and it took me over an hour to track the problem down).

  • Don't be tempted to replace the jQuery each method with this.

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 HTML

<script src="https://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>

Test runner

Ready to run.

Testing in
TestOps/sec
.each()
var count = 0;
a.each(function() {
  $(this).addClass("fred");
});
ready
.quickEach()
a.quickEach(function() {
  this.addClass("fred"); // jQuery object
});
ready
.quickerEach()
a.quickerEach(function() {
  this.addClass("fred"); // jQuery object
});
ready
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.
 
ready

Revisions

You can edit these tests or add more tests to this page by appending /edit to the URL.