jQuery: Fastest method to find Descendents

April 20, 2010 by aaron
jQuery: Fastest method to find Descendents

In jQuery, there are 5 different selectors that can find an element’s descendants. One of these methods, will grab only first-level children but it is included with the other four to demonstrate the differences. By profiling these 5 selectors, we can get a basic idea of which selector is the fastest, but, as you will see from the graphs, the speed of the different browsers heavily influences the speed of the selector. However, looking into the jQuery source itself will demonstrate why certain selectors are faster.

I answered this basic question on StackOverflow just from my experience without reading the jQuery source or performing benchmarks. I was actually surprised that not only was my order correct, but also that jQuery functioned much as I expected it to under the hood. The images and explanations are directly from my answer on StackOverflow. All of the benchmark tests can be run from jsFiddle, but wait a bit before you try it out.

All Descendant Selectors in jQuery

Our methods:

  1. $(".child", $("#parent")); (by using a scope)
  2. $("#parent").find(".child"); (the find() method)
  3. $("#parent").children(".child"); (For immediate children, I use this a lot)
  4. $("#parent > .child"); (via CSS selector)
  5. $("#parent .child");

Ranking the jQuery Selectors

Using a Scope and Find

$(".child", $("#parent")) and $("#parent").find(".child") are identical with the only difference is that method 1 needs to parse the scope passed and translate it to a call to $parent.find(".child").show();.

Let’s take a look into the source to see why this is,

  jQuery.fn = jQuery.prototype = {
    init: function( selector, context ) {
      // Handle HTML strings
      if ( typeof selector === "string" ) {
        if ( match && (match[1] || !context) ) {
            [...]
            // HANDLE: $(expr, context)
            // (which is just equivalent to: $(context).find(expr)
          } else {
            return jQuery( context ).find( selector );
          }

The jQuery source tells us two things:

  1. method 1 and method 2 are exactly equivalent. If anything, method 2 will be slightly faster.

  2. Any other method will be slower because of the large block of if…else statements I removed. Parts of the code will show up later, but basically, if the passed element isn’t an ID and there is no context passed, jQuery has to use regex to try and understand it.

Why you should never use CSS text selectors

$("#parent > .child"); and $("#parent .child"); both need to parse the selector and then just call: $('#parent').children().filter('.child') and $('#parent').filter('.child') respectively.

I never researched it, so didn’t know exactly why this was, but I recently saw this video by Paul Irish where he explains why it takes longer to process this. The answer is long and technical, but the lines I clipped from the jQuery source above basically just look to see if an #id is passed and then grabs that element directly.

When you have a longer CSS selector like $("#parent > .child") jQuery has to load “Sizzle” which is a large and fairly slow CSS-based selectors library. A separate download of Sizzle is only 4KB, but it starts with this beautiful REGEX:

var chunker =
/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g

Yipes! Chunker is a bit more like clunker if you ask me.

A Quick Note on Using .children() versus .find()

Finally, method 3 will always be the fastest because it uses .children() to do the least amount of work and uses the most direct method to get first-level children.

Profiling the Selectors, Speed test

The difference in perforamnce in the different browsers is staggering. The calculations are in computations per second, so the higher the number, the faster the selector is.

On Chrome, Method 3 is the best then method 12 and then 45

jQuery selector performance in Chrome

On Firefox, Method 3 is still best then method 12 and then 45

jQuery selector performance in Firefox 3.6

On Opera, Method 3 is still best then method 45 and then 12

jQuery selector performance in Opera

On IE 8, while slower overall than other browsers, it still follows the Method 3, 1,2,4,5 ordering.

jQuery selector performance on IE8

Overall, method 3 is the overall best method to use as it is called directly and it doesn’t need to traverse more than one level of child elements unlike method 12 and it doesn’t need to be parsed like method 45

Though, keep in mind that in some of these we are comparing apples to oranges as Method 5 looks at all children instead of first-level ones.

Finally, if you want to read all about profiling and perfomance in jQuery check out this slideshow by Paul Irish. It’s a very useful read if you are just starting to learn how to optimize your jQuery.

comments powered by Disqus

Do you want to get in touch?

Let us know what you want to create.

Contact Us