开发者

Which jQuery selection method is faster?

I'm wondering if there's any advantage to using the context parameter when making selections with jQuery versus using a normal CSS scoped selector.

Assuming I have this html:

<div class="contacts">
    <h1>All contacts</h1>
    <div class="contact new">
        <p class="name">Jim Jones</p>
        <p class="phone">(555) 555-1212</p>
    </div>
    <div class="contact new">
        <p class="name">Bob Smith</p>
        <p class="phone">(555) 555-开发者_JAVA百科1213</p>
    </div>
    <div class="contact new">
        <p class="name">Dave Baker</p>
        <p class="phone">(555) 555-1214</p>
    </div>
    <div class="contact">
        <p class="name">Pete Harrison</p>
        <p class="phone">(555) 555-1215</p>
    </div>
    <div class="contact">
        <p class="name">George Donald</p>
        <p class="phone">(555) 555-1216</p>
    </div>
    <div class="contact">
        <p class="name">Chris Root</p>
        <p class="phone">(555) 555-1217</p>
    </div>
</div>

If I want to grab all new contacts (marked by 'new' class) from the contacts div, which method is faster, scales better, etc..?

$('.contacts .new');

Or

$('.new', '.contacts');

jsFiddle

Update

There's a lot of great info strewn throughout the answers and comments. To summarize the major points, in most browsers a single selector scales better when there are multiple .contacts divs. The two selector context method is faster, in most browsers, with only a single .contacts div present.

Something useful to take away from that is we can use one method when selecting inside an element with an id.

$('p:first', '#chapter2'); // get the first paragraph from chapter 2

And use the single selector method for instances where we're selecting from a potentially large group of elements.

$('.chapter p:first-child'); // get the first paragraph from all chapters


Against all (my) odds, seems number 2 is the fastest.

Check it here


$('.contacts .new') should, in theory, scale better because it makes only a single call to the selector engine. For $('.new', '.contacts'), a minimum of two calls are made to the selector function — first to get all elements with class name .contacts, and then further calls for each .contacts element returned.

In summary, as soon as more .contacts elements are thrown into the HTML, a loop is required for the second method and it will slow down significantly. If you're not going to have more .contact elements, you should be using an ID which would be even faster.


IIRC, $('.foo', '.bar') delegates to $('.bar').find('.foo'), so the second should be faster.

The reason $('.foo', '.bar') is faster than $('.foo .bar') is because its executed as native getElementsByClassName by sizzle. A case of a selector that just contains a single class name is checked very early in the code, before any complicated logic is executed.

update: like I thought, using find() is slightly faster: http://jsperf.com/jquery-selection-method/2

update 2: I looked it up in jQuery's code - $('.foo', '.bar') does delegate to $('.bar').find('.foo') - https://github.com/jquery/jquery/blob/master/src/core.js#L171.


Of your two examples the first selector would probably be faster. However, if you assign the context to a variable then use the second method it is MUCH faster.

contacts = $('div.contacts');
$('.new', contacts);

You can see results at http://jsperf.com/jquery-context-with-tagname. If you had a larger HTML document prefixing the class with a tag name would also likely yield better performance.


The second one is undocumented, so you should not use it at all.

The context parameter should be:

A DOM Element, Document, or jQuery to use as context

Ref: http://api.jquery.com/jQuery/

A string is neither of those.

So, you should create a jQuery object from the selector before using at as context:

$('.new', $('.contacts'));

As you are making two jQuery calls, that should be slightly slower. However, both expressions basically do the same work so the difference should not be that big.

Edit:

Testing how the methods scale: http://jsperf.com/jquery-selection-method/4

Shows that the performance differs between browsers. The single selector is slower in most browsers when you have a single .contacts, except Opera where it's really fast. With multiple .contacts elements, the single selector scales better.


http://jsfiddle.net/cvWA7/1/

The results I am getting are that the first selector, $('.contacts .new') is roughly 22% faster.

UPDATE Interesting that Pablo got conflicting results. I wonder if there is something wrong with my test.

UPDATE 2 This was run on Chrome 13

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜