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

Revision 59 of this benchmark created by David Seigle on


Description

The quickEach method will pass a non-unique jQuery instance to the callback meaning that there will be no need to instantiate a fresh jQuery instance on each iteration. Most of the slow-down inherent in jQuery’s native iterator method (each) is the constant need to have access to jQuery’s methods, and so most developers see constructing multiple instances as no issue… A better approach would be quickEach.

Added "quickerEach" implementation (slightly modifies the original quickEach code).

Note that the performance is VERY DIFFERENT when the loop actually does something with the jQuery object. When you use "addClass" in the loop then "quickerEach" performs best, when it is not there, the for-loop performs best. It feels like the JS runtimes are able to realise that the for-loop doesn't actually need to do anything - and optimises for that scenario. That's really clever - but it makes measuring performance difficult.

Optimized the for loop.

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>')).find('a');

  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;
    };
  }());

  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;
    };
  }());
</script>

Test runner

Ready to run.

Testing in
TestOps/sec
.each()
a.each(function() {
  $(this).addClass("wibble");
});
ready
.quickEach()
a.quickEach(function() {
  this.addClass("wibble"); // jQuery object
});
ready
for loop
var jq = jQuery([1]);
for (var i = a.length; i--;) {
  jq[0] = a[i];
  jq.addClass("wibble"); // jQuery object
}
ready
.quickerEach()
a.quickerEach(function() {
  this.addClass("wibble"); // jQuery object
});
ready

Revisions

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