31

I was hoping $('#childDiv2 .txtClass') or $('#childDiv2 input.txtClass') perform better when selecting <input type="text" id="txtID" class="txtClass"/> element. But according to this performance analysis $('.txtClass'); is the best selector among this. I'm using JQuery 1.7.2 Does anybody have explanation for this?

Performance analysis for class selectors

HTML

<div class="childDiv2">
    <input type="text" id="txtID" class="txtClass"/>
    <p class="child">Blah Blah Blah</p>
</div>​

JS

$('.txtClass');
$('#childDiv2 .txtClass')
$('#childDiv2 > .txtClass')
$('input.txtClass')
$('#childDiv2 input.txtClass')
BoltClock
  • 700,868
  • 160
  • 1,392
  • 1,356
Lanka
  • 572
  • 1
  • 7
  • 16

4 Answers4

58

Modern browsers expose a very efficient getElementsByClassName() method that returns the elements having a given class. That's why a single class selector is faster in your case.

To elaborate on your examples:

$(".txtClass")                  =>  getElementsByClassName()

$("#childDiv2 .txtClass")       =>  getElementById(),
                                    then getElementsByClassName()

$("#childDiv2 > .txtClass")     =>  getElementById(),
                                    then iterate over children and check class

$("input.txtClass")             =>  getElementsByTagName(),
                                    then iterate over results and check class

$("#childDiv2 input.txtClass")  =>  getElementById(),
                                    then getElementsByTagName(),
                                    then iterate over results and check class

As you can see, it's quite logical for the first form to be the fastest on modern browsers.

Frédéric Hamidi
  • 258,201
  • 41
  • 486
  • 479
  • So what I can tell is almost every jquery performance tutorials found on the web are incorrect. Even tutorials by some jquery guys like [Addy Osmani](http://addyosmani.com/jqprovenperformance/) – Lanka Jul 28 '12 at 07:41
  • 3
    @Lanka, maybe not *incorrect*, just *outdated*. Technology marches on, and the best performance advice today might very well be wrong next year. Benchmarks, on the other hand, will give you up-to-date numbers. – Frédéric Hamidi Jul 28 '12 at 07:46
  • Yes that is correct. Actually I was wrong in my previous comment. That guy have explained it in the slides. – Lanka Jul 28 '12 at 07:56
  • @FrédéricHamidi I think you are wrongly implying with your answer that the way the reading is done is from left-to-right, when in fact in all modern browsers it's from right-to-left with getElementById(), "then" getElementsByTagName() etc. The operations are these, just they don't happen in that order. – daremkd Jan 21 '16 at 16:23
  • @daremkd, it's not quite RTL (see the comments under [this related answer](http://stackoverflow.com/a/5813672/464709)). Also, it is done when applying styles, i.e. when the goal is to *find all selectors that match a given element*. `querySelector*()` and especially the Sizzle engine do not share the same goals (theirs is to *find all the elements that match a given selector*) and I doubt they would choose RTL at the cost of performance (especially Sizzle). – Frédéric Hamidi Jan 21 '16 at 16:32
  • @FrédéricHamidi Oh, so as far as I understand, say you have "input.a a#b", "input.a" and "a#b" are compound selectors, so in this case, "a#b" will be selected first (but not evaluated necessarily in RTL order), right? – daremkd Jan 21 '16 at 16:50
8
var obj = document.getElementById("childDiv");
xxx = obj.getElementsByClassName("txtClass");

is 30x faster.

http://jsperf.com/selectors-perf/6

klaus
  • 81
  • 1
  • 2
6

CSS Selectors are parsed from right to left. So your example

$('#childDiv2 .txtClass')

will take two actions to complete. First find all elements with class txtClass. Then check each element for being a child of the element with the id childDiv2.

$('.txtClass')

This selector will just take one action. Find all elements with class txtClass

Have a look at this article on css-tricks.com

Andreas
  • 21,535
  • 7
  • 47
  • 56
  • As I know sizzle optimize this query. So it's work differently than your explanation. It's first select the childDiv2 and then search for txtClass in it's children. – Lanka Jul 28 '12 at 15:35
  • actually, the first code line shown requires checking each .txtClass element to see if it is a DESCENDANT of #childDiv2. That requires examining ALL the ancestors of each .txtClass. – ToolmakerSteve Aug 14 '14 at 05:49
1

Looks like it also depends on the density of the elements with the class among the elements of the type.

I ran the tests with Google Chrome Version 30.0.1599.69 using JQuery 1.10.1. Feel free to try it on another browser and/or using another JQuery version.

I tried to run the following tests:

  1. Sparse (10% of the div's have the class) link to the test on jsbin

  2. Dense (90% of the div's have the class) link to the test on jsbin

Looks like in the Dense case div.class wins, but in the Sparse case .class wins.

Alexander
  • 7,484
  • 4
  • 51
  • 65