Reputation: 40311
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?
Upvotes: 74
Views: 30418
Reputation: 9671
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.
Upvotes: 5
Reputation: 221
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:
.find
, .children
etc.: $('#foo').find('div')
$('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.Upvotes: 5
Reputation: 1
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");
Upvotes: 0
Reputation: 19409
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.)
Upvotes: 0
Reputation: 60027
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.
Upvotes: 0
Reputation: 871
Here is how to icrease performance of your jQuery selectors:
$('.select', this)
)Upvotes: 4
Reputation: 102725
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.
Upvotes: 14
Reputation: 4173
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!
Upvotes: 3
Reputation: 4173
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!
Upvotes: 0
Reputation: 415665
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.
Upvotes: 3
Reputation: 12230
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.
Upvotes: 35
Reputation: 38740
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.
Upvotes: 0