46

Basically, is

$("#someid")

or

$(".someclass")

faster than

$("[someattr='value']")

I would imagine that it is (that is, selection by id is fastest, then class, then attribute), but does anyone know for sure?

Jay
  • 3,471
  • 4
  • 35
  • 49
  • 3
    Not so black and white as everyone would have you believe: http://jsperf.com/attribute-vs-class-selection/3 class vs. attribute look neck and neck. – davin Jun 23 '11 at 21:17
  • I was surprised (and made assumptions) when I tested my pages - I found some selection structures to NOT be as performant as others on my ACTUAL page. I test more now :) – Mark Schultheiss Jun 23 '11 at 21:39
  • I was about to ask the same question and you saved me some time. – Helen Araya Jan 27 '16 at 16:20

6 Answers6

72

ID is absolutely the fastest. Part of the reason is that ID is supposed to be unique, so the API stops searching after the ID is found in the DOM.

If you must use a class or attribute selector, you can improve performance by specifying the optional context parameter.

For example...

$(".someclass", "#somecontainer")

Where somecontainer is something like a div, surrounding an element with class someclass. This can offer a huge performance benefit in the cases where somecontainer comprises a small fraction of the DOM.


UPDATE:

I did some tests a couple years ago around the context parameter. After reading the comments below I was curious if anything has changed. Indeed, it seems the scene has changed somewhat with today's browsers. Maybe it also has to do with improvements in jQuery? I don't know.

Here are my results with 10,000 iterations (code is below):

IE9

$(".someclass") - 2793 ms

$(".someclass", "#somecontainer") - 1481 ms

Chrome 12

$(".someclass") - 75 ms

$(".someclass", "#somecontainer") - 104 ms

Firefox 3.6

$(".someclass") - 308 ms

$(".someclass", "#somecontainer") - 357 ms

So among these big 3 modern browsers, the context parameter only seems to help IE9. Older browsers will also benefit from the context parameter. But considering the prevalence of each of these browsers and averaging everything out, the net gain is somewhat of a wash now.

And here's the code in case anyone wants to try it themselves...

<html>
    <head>
        <script type="text/javascript" src="http://code.jquery.com/jquery-1.6.1.min.js"></script>
        <script type="text/javascript">
            $(document).ready(function(){

                startTime = new Date().getTime();               
                for (i = 0; i < 10000; i++)
                {
                    s = $(".someclass");
                }           
                $("#withoutcontext").html(elapsedMilliseconds(startTime));


                startTime = new Date().getTime();
                for (i = 0; i < 10000; i++)
                {
                    s = $(".someclass", "#somecontainer");
                }           
                $("#withcontext").html(elapsedMilliseconds(startTime));

            });

            function elapsedMilliseconds(startTime)
            {
                var n = new Date();
                var s = n.getTime();
                var diff = s - startTime;
                return diff;
            }
        </script>
    </head>
    <body>
        <h1>jQuery Selector Performance: Context vs No Context</h1>

        <h2>$(".someclass")</h2>
        <span id="withoutcontext">---</span> ms<br /><br />

        <h2>$(".someclass", "#somecontainer")</h2>
        <span id="withcontext">---</span> ms<br /><br />

        <hr />

        <p class="a">a</p>
        <p class="b">b</p>
        <p class="c">c</p>
        <p class="a">a</p>
        <p class="b">b</p>
        <p class="c">c</p>
        <p class="a">a</p>
        <p class="b">b</p>
        <p class="c">c</p>
        <p class="a">a</p>
        <p class="b">b</p>
        <p class="c">c</p>
        <p class="a">a</p>
        <p class="b">b</p>
        <p class="c">c</p>
        <div id="somecontainer">
            <p class="a">a</p>
            <p class="b">b</p>
            <p class="c">c</p>
            <p class="someclass">someclass</p>
        </div>
        <p class="a">a</p>
        <p class="b">b</p>
        <p class="c">c</p>
        <p class="a">a</p>
        <p class="b">b</p>
        <p class="c">c</p>
        <p class="a">a</p>
        <p class="b">b</p>
        <p class="c">c</p>
        <p class="a">a</p>
        <p class="b">b</p>
        <p class="c">c</p>
        <p class="a">a</p>
        <p class="b">b</p>
        <p class="c">c</p>
    </body>
</html>
Steve Wortham
  • 21,740
  • 5
  • 68
  • 90
  • What if I want **every element** with that class, no matter where it's located? (More realistically, every such element within `body`, but would the solution then be to add an ID to `body`?) – BoltClock Jun 23 '11 at 21:22
  • Then leave off the context parameter. I simply mentioned it because I feel it's often forgotten. I haven't tested an ID on the body, but I wouldn't think that would help much. – Steve Wortham Jun 23 '11 at 21:25
  • @Steve I think it's true for old browsers only. For modern browsers the context parameter makes this process even slower. – Karolis Jun 23 '11 at 21:29
  • @BoltClock body is optimized within the jQuery code as there can ONLY be one. You would need to test as class might be faster in some browsers. – Mark Schultheiss Jun 23 '11 at 21:32
  • 1
    I actually found in some complex pages the class-within-a-div assumption was not always true as most performant. – Mark Schultheiss Jun 23 '11 at 21:41
  • 1
    @Mark - Wow. You're right. It's amazing how things change in a couple years. You can see my results above. – Steve Wortham Jun 23 '11 at 22:07
  • 5
    @Steve Wortham: Kudos for the tests. – Jay Jun 23 '11 at 22:23
  • Chrome 47 `$(".someclass") 24 ms $(".someclass", "#somecontainer") 34 ms` using jQuery 1.11 and 2.1.4 show similar relative results. Edge: `$(".someclass") 37 ms $(".someclass", "#somecontainer") 72 ms` IE 11 `$(".someclass") 25 ms $(".someclass", "#somecontainer") 39 ms` SO the pattern holds except IE where it went the same as others – Mark Schultheiss Dec 24 '15 at 15:33
  • NOTE: DO NOT do `$("#somecontainer .someclass");` where it jumps from 34 up to 60-72 ms due to the right to left sizzle engine selection. and `$("#somecontainer> .someclass");` is worse > 72+ in relative tests (6-8% slower – Mark Schultheiss Dec 24 '15 at 15:39
11

Selecting by ID is the fastest, because it maps directly to getElementByID, the other 2 has to check each element to determine the selected elements.

If you must select using class or attribute, then try enclosing the search in a ID. ex.

$("#someid .someclass")
a programmer
  • 959
  • 4
  • 8
  • 1
    I suppose that's partially true, but select by class would also map to getElementsByClassName right? – Jay Jun 23 '11 at 21:17
  • 4
    Actually, the `#id .class` syntax won't help. You should use the optional context parameter if you want any performance benefit. – Steve Wortham Jun 23 '11 at 21:21
  • Yes, it maps to getElementsByClassName, but not in IE6-8. Firefox, Opera, Safari and Chrome support it. – a programmer Jun 23 '11 at 21:22
  • This is definitely the right answer, as this utilizes the querySelectorAll() method usage, and is much faster than $(".someclass", "#somecontainer") – Vasil Popov Jun 24 '15 at 13:40
7

ID is unique and if you only want to select one/first element here the equivalent

$("#someid") => 75,695 ops/sec, fastest

$(.unique_class') => 45,257 ops/sec, 40% slower : only one class on page

$(".someclass").first() => 42,217 ops/sec, 46% slower : multiple class on page, select first element

$(".someclass:eq(0)") => 18,324 ops/sec, 76% slower : multiple class on page, select element at selected index

Test url: http://jsperf.com/jquery-selector-speed-tests/98

ewwink
  • 18,382
  • 2
  • 44
  • 54
7

ID and class selectors, at least when used by themselves, tend to be faster, whether for jQuery or for CSS. This is due largely to the fact that browsers have optimized algorithms for IDs and classes in their DOM/CSS engines.

In modern browsers with recent versions of jQuery, any selector strings that are understood as supported CSS selectors by a browser will be handled by document.querySelectorAll(), offering maximum performance as long as standard CSS selectors are used. Non-standard selectors or older browsers are taken care of by jQuery and/or the Sizzle library, which do their best to make use of the DOM's get-element(s) methods to traverse the DOM.

The most important thing to remember is that performance will vary from browser (version) to browser (version) because of differing DOM implementations. At least, that's how I believe things are.

BoltClock
  • 700,868
  • 160
  • 1,392
  • 1,356
  • Modern browser being IE 8+, Chrome, Safari, Firefox. So any browser that isn't business mandated. – timw4mail Jun 23 '11 at 21:26
  • For css attribute selection is important too (as there is attribute selectors) so it's optimize too. – Daniel Jun 23 '11 at 22:09
2

The id will always be fastest as it it unique on the page. The class "may" be faster than an attribute but it depends.

The real kicker here is selection of a class within and ID may NOT be faster than just selection of the class. It will depend on the page and browser. In my testing, selection of a complex page with a limited number of elements with a "class" where the parent of the class element had an id such as:

<div id='iamout'>
  <div class='aonther'>
    <div class='iamin'>stuff</div>
    <div class='iamin'>stuff</div>
  </div>
</div>

a selector such as $('.iamin','#iamout') was not always as fast as $('.iamin')

Not all browsers support select by classname (natively), but modern/newer ones do and thus it might offer better performance depending upon which browser you have.

If you need to have optimum performance you will need to test your exact page.

Mark Schultheiss
  • 32,614
  • 12
  • 69
  • 100
0

Id is fastest, because it is the only element that can have that identifier. Many objects could possibly have the same class name. Someone could verify this, but it would seem like the document would not need to be traversed any further once the id was found. For classes this may not be the case?? HTH

webtrifusion
  • 4,536
  • 2
  • 14
  • 9