Selector for best performance in jQuery?

2019-06-21 22:31发布

问题:

I just spent 2 hours reading online guides and blogs about jQuery selectors. Everybody says different things and every last one of them seem to be so sure. I need an expert opinion from Stackoverflow.

$(' #my-id div.my-class ')

$(' #my-id .my-class ')

$(' div.my-class ')

$(' .my-class ')


<div id="my-id">
    <div class="..">
        <div class=".."> Awesome stuff! </div>
        <div class="my-class">
            <p> I like carrots! </p>
        </div>
    </div>
</div>

Which is the best selector in your opinion? I also need a short explanation because rewriting thousands of lines of code is at stake. It happens one way or another, I just don't want to do it twice.

Also, if I wanted to get <p>, should I give it a class because jQuery and CSS reads selectors from right to left?

Is there even such thing as too many classes or is it because people are just lazy?


If the same rules apply to CSS, just let me know. One word is enough.

回答1:

If all you want is all instances of DOM elements that match .my-class, then I see no reason why you should use anything other than:

$('.my-class')

The others are all more specific selectors and can be used if you want to narrow the selector to more than just $('.my-class').

If you're really trying to fully optimize performance, than using jQuery in the first place is likely not the desired choice as the overhead of jQuery initialization and jQuery objects tends to slow things down. You use jQuery because it's quick to code and offers great cross-browser support and a bunch of useful methods. You don't use jQuery to optimize performance.

If you really want to compare the performance of your four jQuery options, then you will have to design up a representative set of HTML (which has to include lots of other things to be truly representative of a real world situation) and then test each of your selectors in some benchmarking tool like jsperf and run that test in all browsers that you care about and with the versions of jQuery that you will be using and then see if you can come to some particular conclusion.

This smells like an attempt at premature optimization. Write your code first as simply as possible and only spend time optimizing performance when you've actually measured that you have a performance issue and that this is the place in your code where the performance bottleneck is. 99.99% of the time, the performance of a particular selector is not going to make one iota of difference in your code. Code simply and without complication first. In the 0.01% of the time that you actually want to optimize your code, you will probably care so much about performance that you will either pre-cache the list of elements or you will not code it in jQuery in order to avoid the jQuery object setup and overhead.

Here's a jsPerf: http://jsperf.com/jquery-selector-comparison-specificity/4. This shows relatively little difference between the options when tested in the latest versions of Chrome, Firefox and IE. There is a slight bias in favor of the $('.my-class') option.

And for reference, you will find that:

document.getElementsByClassName("my-class")

is as much as 50x faster than any of the jQuery options.

Here's a screenshot of the jsperf results in Chrome:

Conclusions

  1. For normal coding where you haven't proven you actually have a performance issue that you need to spend time optimizing, use the simplest selector that meets your selection objective.

  2. If it's really performance critical, use plain Javascript, not jQuery.



回答2:

According to jQuery's Docs:

Beginning your selector with an ID is always best.

// Fast:
$( "#container div.robotarm" );

// Super-fast:
$( "#container" ).find( "div.robotarm" );

Be specific on the right-hand side of your selector, and less specific on the left.

// Unoptimized:
$( "div.data .gonzalez" );

// Optimized:
$( ".data td.gonzalez" );

Avoid Excessive Specificity

$( ".data table.attendees td.gonzalez" );

// Better: Drop the middle if possible.
$( ".data td.gonzalez" );

Avoid the Universal Selector. Selections that specify or imply that a match could be found anywhere can be very slow.

$( ".buttons > *" ); // Extremely expensive.
$( ".buttons" ).children(); // Much better.

$( ".category :radio" ); // Implied universal selection.
$( ".category *:radio" ); // Same thing, explicit now.
$( ".category input:radio" ); // Much better.

Now, with all that said...

It's good to be mindful of this stuff and to optimize where possible, but realistically many of these will, more or less, end up being micro optimizations. If you're looking to trim fat for a performance boost there are probably better places to look.

Go ahead... Burn me as a heretic... I'm not scared...



回答3:

I did a benchmark test that show me it's better to choose more specific selectors.

I tested this HTML :

<div id="my-id">
    <div class="grand">
        <div class="parent"> Awesome stuff! </div>
        <div class="my-class">
            <p> I like carrots! </p>
        </div>
    </div>
</div>
<script src='https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.js'></script>

With 8 different selectors :

$(' div#my-id div.grand div.parent div.my-class ').css("background-color", "#cccccc"); //case-1
$(' #my-id .grand .parent div.my-class ').css("background-color", "#cccccc"); //case-2
$(' #my-id .grand .parent .my-class ').css("background-color", "#cccccc"); //case-3
$(' div#my-id div.my-class ').css("background-color", "#cccccc"); //case-4
$(' #my-id div.my-class ').css("background-color", "#cccccc"); //case-5
$(' #my-id .my-class ').css("background-color", "#cccccc"); //case-6
$(' div.my-class ').css("background-color", "#cccccc"); //case-7
$(' .my-class ').css("background-color", "#cccccc"); //case-8

And results showed me that case-1, case-2 and case-3 are better than the others. you can see the result here.