views:

52

answers:

3

I have the following HTML:

...
<div id="panel">
    <div class="abc">
        <p class="xyz">Hello</p>
    </div>
</div>
...

Question: What's the fastest way with JQuery for me to access the p.xyz element? I've read some performance reviews but they don't account for all different scenarios.

I could do the following, but don't know how to test which is the fastest.

$('.xyz');
$('p.xyz');
$('#panel .xyz');
$('#panel p.xyz');
$(".xyz", $('#panel'));

I'm sure there are even more ways to access that node as well.

>>> Which is the fastest and recommended way?

+1  A: 

The fastest selector is always the ID selector, or a selector that descends from it. In your case:

$('#panel .xyz'); and $('#panel p.xyz');

will have about the same speed, so close it doesn't matter...but the non-ID ones are orders of magnitude behind in performance.

There's also already a healthy dose of answers on this in another question on SO.

Nick Craver
I read once that, "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." http://stackoverflow.com/questions/46214/good-ways-to-improve-jquery-selector-performance/2062027#2062027
Allen
So are you certain that $('#panel p.xyz') would be faster than just $('p.xyz') ?
Allen
This is true to some extent....however in jQuery's case Sizzle knows this, and immediately shortcuts to the ID. If you have multiple elements with the same ID it will be unpredictable, but that is invalid HTML anyway, so that's how sizzle behaves...as it should be.
Nick Craver
@Allen: Yes, it's much faster...and just for completeness sake `$('#panel p.xyz');` is faster than `$('#panel .xyz');`, class selectors are by far the slowest in the examples you listed...no matter how far down they are.
Nick Craver
+1  A: 

"...but don't know how to test which is the fastest."

Have a look at firebug. In particular, the Javascript profiler. Basically:

  • Install the firebug Firefox plugin.
  • Right click on the little bug icon at the bottom right of firefox. Select 'enable all panels'.
  • Click on the 'console' tab.
  • Click on the 'profile' option. Hovering the mouse over it says 'Profile Javascript execution time'. The rest should be fairly intuitive. If you find that it is not, there are plenty of tutorials to help you out.

You can now experiment with different selectors/DOM structures and measure their relative execution times for a better understanding of which selectors actually perceivably impact the performance of your web application.

Hope that helps.

karim79
+3  A: 

Any time you can use an ID selector it will be faster. jQuery selector engine (Sizzle) reads from right to left. The only exception being if on the far left is an id, then that id is used to scope the search.

Additionally, since jQuery uses native browser functionality wherever possible, always supply the tag name when using a class selector.

In your series of options as to "what is faster", this would perform the fastest:

$('#panel p.xyz');

Because it would scope the search to a single element, then find the p tags, then drop out of the selection all the ones that don't have the proper class.

In some browsers, with a lot of other sibling p tags that shouldn't match your query, it will perform a lot faster than:

$('#panel .xyz');

Just remember that jQuery uses as many native features as possible. Every single mainstream browser has getElementById so use an id where possible.

Next, every browser has a getElementsByTagName. What some browsers do not have is getElementsByClassName. So help jQuery help you by using an id where possible to scope the search, and by pairing tag names with the class for class searches.

Never pass a jQuery object as the scope parameter

One thing you should NEVER do, is your last example:

$(".xyz", $('#panel'));

That would have no speed impact (and in a loop it would be slower) than using a normal string. Only every pass a DOM element into this parameter. This can be very useful when you have the DOM element already:

$("#panel").click(function(){
  var p = $("p.xyz", this); // This is fast
});
Doug Neiner