jQuery.fn.each vs. jQuery.fn.quickEach
JavaScript performance comparison
Info
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 bug fix to roviury's version (it was previous faster because it wasn't doing any work).
Added James Padolsey's original quickEach for comparison.
Added "addClass" to body of loops so that JS runtime can't get fancy ideas about optimising the entire body away.
Added quickerEach for comparison.
Added my previous simple while-loops that demonstrate that quickEach should really not be required.
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>')).find('a');
//Original version by James Padolsey.
jQuery.fn.origQuickEach = (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;
};
}());
//Updated version supplied by roviury.
jQuery.fn.updatedQuickEach = (function(jq) {
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) {
throw e;
} finally {
delete jq[0];
}
return this;
};
})(jQuery([1])); //Bug-fix: Previously this was just jQuery().
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>
Preparation code output
Test runner
Warning! For accurate results, please disable Firebug before running the tests. (Why?)
Java applet disabled.
| Test | Ops/sec | |
|---|---|---|
.each |
|
pending… |
Original .quickEach |
|
pending… |
Updated .quickEach |
|
pending… |
quickerEach |
|
pending… |
while loop |
|
pending… |
while without body |
|
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:
- Revision 1: published by James Padolsey
- Revision 2: published by "Cowboy" Ben Alman
- Revision 3: published by "Cowboy" Ben Alman
- Revision 9: published by NilColor
- Revision 13: published
- Revision 14: published
- Revision 15: published
- Revision 18: published
- Revision 19: published
- Revision 22: published by mhitza
- Revision 27: published
- Revision 28: published by Test
- Revision 29: published
- Revision 30: published by Erwan Legrand
- Revision 31: published
- Revision 32: published
- Revision 33: published
- Revision 34: published by Vaibhav
- Revision 35: published
- Revision 36: published
- Revision 37: published
- Revision 38: published
- Revision 39: published
- Revision 41: published by Jason
- Revision 42: published by Dim
- Revision 47: published by Andy Harman
- Revision 48: published by Andy Harman and last updated
- Revision 50: published by private_face
- Revision 54: published
- Revision 56: published by David Seigle
- Revision 58: published by Andy Harman
- Revision 59: published by David Seigle
- Revision 63: published by Andy Harman
- Revision 64: published by roviury
- Revision 66: published by Andy Harman
- Revision 69: published by Andy Harman and last updated
- Revision 70: published
- Revision 71: published
- Revision 73: published
- Revision 74: published
- Revision 76: published
- Revision 77: published
- Revision 78: published by Jeffrey
- Revision 79: published
- Revision 80: published
- Revision 81: published by nod_ and last updated
- Revision 82: published by Andy Harman
- Revision 83: published by Kirill
- Revision 85: published
1 comment
SORRY - I'm an idiot!
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.