Good ways to improve jQuery selector performance?

I'm looking for any way that I can improve the selector performance of a jQuery call. Specifically things like this:

Is $("div.myclass") faster than $(".myclass")

I would think it might be, but I don't know if jQuery is smart enough to limit the search by tag name first, etc. Anyone have any ideas for how to formulate a jQuery selector string for best performance?


Solution 1:

There is no doubt that filtering by tag name first is much faster than filtering by classname.

This will be the case until all browsers implement getElementsByClassName natively, as is the case with getElementsByTagName.

Solution 2:

In some cases, you can speed up a query by limiting its context. If you have an element reference, you can pass it as the second argument to limit the scope of the query:

$(".myclass", a_DOM_element);

should be faster than

$(".myclass");

if you already have a_DOM_element and it's significantly smaller than the whole document.

Solution 3:

As Reid stated above jQuery is working from the bottom up. Although

that means $('#foo bar div') is a lot slower than $('bar div #foo')

That's not the point. If you had #foo you wouldn't put anything before it in the selector anyway since IDs have to be unique.

The point is:

  • if you are subselecting anything from an element with an ID then select the later first and then use .find, .children etc.: $('#foo').find('div')
  • your leftmost (first) part of the selector can be less efficient scaling to the rightmost (last) part which should be the most efficient - meaning if you don't have an ID make sure you are looking for $('div.common[slow*=Search] input.rare') rather than $('div.rare input.common[name*=slowSearch]') - since this isn't always applicable make sure to force the selector-order by splitting accordingly.

Solution 4:

In order to fully comprehend what is faster, you have to understand how the CSS parser works.

The selector you pass in gets split into recognizable parts using RegExp and then processed piece by piece.

Some selectors like ID and TagName, use browser's native implementation which is faster. While others like class and attributes are programmed in separately and therefore are much slower, requiring looping through selected elements and checking each and every class name.

So yes to answer your question:

$('tag.class') is faster than just $('.class'). Why? With the first case, jQuery uses the native browser implementation to filter the selection down to just the elements you need. Only then it launches the slower .class implementation filtering down to what you asked for.

In the second case, jQuery uses it's method to filter each and every element by grabbing class.

This spreads further than jQuery as all javascript libraries are based on this. The only other option is using xPath but it is currently not very well supported among all browsers.