Good ways to improve jQuery selector performance?

JavascriptJqueryPerformanceCss Selectors

Javascript Problem Overview


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?

Javascript Solutions


Solution 1 - Javascript

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 - Javascript

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 - Javascript

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.

Solution 4 - Javascript

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 5 - Javascript

Here is how to icrease performance of your jQuery selectors:

  • Select by #id whenever possible (performance test results ~250 faster)
  • Specify scope of your selections ($('.select', this))

Solution 6 - Javascript

I'll add a note that in 99% of web apps, even ajax heavy apps, the connection speed and response of the web server is going to drive the performance of your app rather than the javascript. I'm not saying the you should write intentionally slow code or that generally being aware of what things are likely to be faster than others isn't good.

But I am wondering if you're trying to solve a problem that doesn't really exist yet, or even if you're optimizing for something that might change in the near future (say, if more people start using a browser that supports getElementsByClassName() function referred to earlier), making your optimized code actually run slower.

Solution 7 - Javascript

Another place to look for performance information is Hugo Vidal Teixeira's Performance analysis of selectors page.

http://www.componenthouse.com/article-19

This gives a good run down of speeds for selector by id, selector by class, and selector prefixing tag name.

The fastest selectors by id was: $("#id")

The fastest selector by class was: $('tag.class')

So prefixing by tag only helped when selecting by class!

Solution 8 - Javascript

I've been on some of the jQuery mailing lists and from what I've read there, they most likely filter by tag name then class name (or vice versa if it was faster). They are obsessive about speed and would use anything to gain a smidgen of performance.

I really wouldn't worry about it too much anyway unless you are running that selector thousands of times/sec.

If you are really concerned, try doing some benchmarking and see which is faster.

Solution 9 - Javascript

Consider using Oliver Steele's Sequentially library to call methods over time instead of all at once.

http://osteele.com/sources/javascript/sequentially/

The "eventually" method helps you call a method after a certain period of time from its initial call. The "sequentially" method lets you queue several tasks over a period of time.

Very helpful!

Solution 10 - Javascript

A great tip from a question I asked: Use standard CSS selectors wherever possible. This allows jQuery to use the Selectors API. According to tests performed by John Resig, this results in near-native performance for selectors. Functions such as :has() and :contains() should be avoided.

From my research support for the Selectors API was introduced with jQuery 1.2.7, Firefox 3.1, IE 8, Opera 10, Safari 3.1.

Solution 11 - Javascript

If I am not mistaken, jQuery also is a bottom up engine. That means $('#foo bar div') is a lot slower than $('bar div #foo'). For example, $('#foo a') will go through all of the a elements on the page and see if they have an ancestor of #foo, which makes this selector immensely inefficient.

Resig may have already optimized for this scenario (it wouldn't surprise me if he did - I believe he did in his Sizzle engine, but I am not 100% certain.)

Solution 12 - Javascript

I believe that selecting by ID first is always faster:

$("#myform th").css("color","red");

should be faster than

$("th").css("color","red");

However, I wonder how much chaining helps when starting with the ID? Is this

$("#myform").find("th").css("color","red")
.end().find("td").css("color","blue");

any faster than this?

$("#myform th").css("color","red");
$("#myform td").css("color","blue");

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionJC GrubbsView Question on Stackoverflow
Solution 1 - JavascriptkamensView Answer on Stackoverflow
Solution 2 - JavascriptMatthew CrumleyView Answer on Stackoverflow
Solution 3 - JavascriptDmitri FarkovView Answer on Stackoverflow
Solution 4 - JavascriptPhilippView Answer on Stackoverflow
Solution 5 - JavascriptjQuery LoverView Answer on Stackoverflow
Solution 6 - JavascriptJoel CoehoornView Answer on Stackoverflow
Solution 7 - JavascriptEvan MoranView Answer on Stackoverflow
Solution 8 - JavascriptRyan DohertyView Answer on Stackoverflow
Solution 9 - JavascriptEvan MoranView Answer on Stackoverflow
Solution 10 - JavascriptAlex AngasView Answer on Stackoverflow
Solution 11 - JavascriptReidView Answer on Stackoverflow
Solution 12 - JavascriptLawrenceView Answer on Stackoverflow