6

My question is related to DOM parsing getting triggered, i would like to know why it's faster to use a CSS ID selector than a Class selector. When does the DOM tree have to be parsed again, and what tricks and performance enhancements should I use... also, someone told me that if I do something like

var $p = $("p");  
$p.css("color", "blue"); 
$p.text("Text changed!");

instead of

$("p").css("color", "blue");  
$("p").text("Text changed!"); 

improves performance, is this true for all browsers? Also how do I know if my DOM tree has been re-parsed?

Astronaut
  • 6,691
  • 18
  • 61
  • 99
  • CSS selector parsing performance alone is microscopic enough. Throwing jQuery's different ways of interpreting different selectors (CSS or non-CSS) into the mix just makes everything unnecessarily confusing. It's not worth agnonizing over these nuances. – BoltClock Apr 17 '12 at 14:04
  • http://www.artzstudio.com/2009/04/jquery-performance-rules/ lists many rules for jquery perf improvement – rt2800 Apr 17 '12 at 14:06
  • 1
    Also note that you can method chain. So you can do `$('p').css('').text('').morestuff()` to improve performance too – mrtsherman Apr 17 '12 at 14:07
  • yep, my only caveat with chaining is that sometimes you get lost in the chain, also harder to debug, unless there is a trick for doing it differently? I guess i will have to get used to it, it's the jQuery way of doing many things. – Astronaut Apr 17 '12 at 14:37

3 Answers3

10

Well, an #id selector is faster than class selectors because: (a) there can only be one element with a given id value; (b) browsers can hold a map id -> element, so the #id selector can work as quick as a single map lookup.

Next, the first option suggested above is definitely faster, as it avoids the second lookup, thereby reducing the total selector-based lookup time by a factor of 2.

Last, you can use Chrome Developer Tools' Selector Profiler (in the Profiles panel) to profile the time it takes a browser to process selectors in your page (match + apply styles to the matching elements.)

Alexander Pavlov
  • 31,598
  • 5
  • 67
  • 93
  • Hey, didn't know about Selector Profiler. Thanks! +1 for me. – mrtsherman Apr 17 '12 at 14:07
  • Only a JavaScript selector library would treat a CSS ID selector as a `getElementById()` call, and retrieve the first element with the matching ID. Strictly speaking, a conforming CSS selector engine needs to match *all* elements with a given ID to that ID selector, even if there is more than one, so if a browser holds such a map, it won't be relevant to this particular matching procedure. But granted we're talking about jQuery here... – BoltClock Apr 17 '12 at 14:07
  • @BoltClock'saUnicorn: I know you are fond of specs :), so [this one](http://www.w3.org/TR/1999/REC-html401-19991224/struct/global.html#adef-id) says that the `id` attribute value must be **unique** in a document. The browser behavior in the case of several elements having the same `id` value is undefined otherwise (definitely more so, if `document.getElementById()` is used.) – Alexander Pavlov Apr 17 '12 at 14:13
  • @AlexanderPavlov: That's HTML, not CSS, which explains why DOM implementation use `document.getElementById()`. Good call, though. – BoltClock Apr 17 '12 at 14:13
  • Apologies for the wrong reference. [The CSS2 spec ID Selectors chapter](http://www.w3.org/TR/CSS2/selector.html#id-selectors) says that "whatever the document language, an ID attribute can be used to uniquely identify its element." – Alexander Pavlov Apr 17 '12 at 14:17
  • @Alexander Pavlov: According to the comments [here](http://stackoverflow.com/questions/5797014/css-selectors-parsed-right-to-left-why), that's informative, and has no impact on the effect of CSS ID selectors on a document. Also see [my recent answer elsewhere](http://stackoverflow.com/a/8753329/106224). I'm probably making unnecessary comments here, though, as like I mentioned we're talking jQuery/JS here. Just some extra info, though! – BoltClock Apr 17 '12 at 14:19
  • Hmm... Looking at the spec, I didn't find any sign of the quote above being informative. [Moreover](http://www.w3.org/TR/css3-selectors/#id-selectors), "An ID selector represents an element instance that has an identifier that matches the identifier in the ID selector." Supposedly, _a single instance_. – Alexander Pavlov Apr 17 '12 at 14:25
  • Thank you for the additional information. Very helpful! I feel like a total newb in JS/JQuery, well I am :) I have found that there are a lot of tricks one has to pay attention to. – Astronaut Apr 17 '12 at 14:34
  • On a side note, WebKit _does_ support ID selector matching for multiple elements with the same ID. I will clarify this with the author of the CSS package once he's available, but presumably, this is to avoid artifacts in broken documents (having multiple elements with the same ID). – Alexander Pavlov Apr 17 '12 at 14:36
  • @AdamSurfari: you don't have to, most of the time. As the current author/maintainer of the CSS package in WebKit said (close to the original text), "If a selector is slow, we should optimize WebKit" [rather than a web developer should optimize his selectors]. – Alexander Pavlov Apr 17 '12 at 14:39
1

I encourage you to make your own performance tests whenever you have a doubt. You can get more info on how to do that here: How do you performance test JavaScript code?. Once you've tested performance on your own, you'll never forget the results.

In particular, the execution of the $() function on a given jquery selector must obtain the matching DOM nodes. I'm not sure exactly how this works but I'm guessing it is a combination of document.getElementById(), document.getElementsByTagName() and others. This has a processing cost, no matter how small it may be, if you call it only once and then reuse it you save some processing time.

Community
  • 1
  • 1
1

An ID selector is faster than a class selector because there is only one element with an ID but many elements could share a class and they have to be searched.

The code below is needlessly parsing the DOM twice, so of course it will be slower:

$("p").css("color", "blue");  
$("p").text("Text changed!"); 
Steve Wellens
  • 20,506
  • 2
  • 28
  • 69