168

I have heard that querySelector and querySelectorAll are new methods to select DOM elements. How do they compare to the older methods, getElementById and getElementsByClassName in terms of performance and browser support?

How does the performance compare to using jQuery's query selector?

Is there a best practice recommendation for which method to use?

Matthias Braun
  • 28,341
  • 18
  • 134
  • 157
goesToEleven
  • 1,763
  • 2
  • 10
  • 4
  • 1
    Define better. They're almost entirely different. –  Nov 10 '14 at 16:27
  • 5
    This is like asking "is a single-size spanner better than an adjustable spanner?" The answer is: they are more powerful and more flexible, and so on many occasions superior, but `getElementById` and `getElementsByClassName` are still ideal for the purposes their names describe. – lonesomeday Nov 10 '14 at 16:27
  • If you're asking specifically about the places where they overlap, then it all depends. `qS` and `qSA` may be slower (or maybe not). `qSA` has broader support overall than `gEBCN`. `gEBCN` returns a "live list" and `qSA` does not. –  Nov 10 '14 at 16:29
  • 2
    Oh, and `qS/qSA` can be used from any element context, but `gEBI` can only be used from the `document` context. –  Nov 10 '14 at 16:33
  • 5
    `getElementById` matches the `id` attributes to find DOM nodes, while `querySelector` searches by selectors. So for an invalid selector e.g `
    `, `getElementById('1')` would work while `querySelector('#1')` would fail, unless you tell it to match the `id` attribute (e.g `querySelector('[id="1"]')`.
    – Ismail Dec 22 '18 at 11:06
  • 4
    Just an FYI for anyone reading this, but `querySelector` and `querySelectorAll` are fully supported now. https://caniuse.com/#feat=queryselector – jarrodwhitley Jun 11 '19 at 01:37
  • This post looks rather like a very old/outdated conversation. – carloswm85 Jun 18 '21 at 11:15

2 Answers2

180

"Better" is subjective.

querySelector is the newer feature.

getElementById is better supported than querySelector.

querySelector is better supported than getElementsByClassName but querySelector gives you a static node list while getElementsByClassName gives you a live node list.

querySelector lets you find elements with rules that can't be expressed with getElementById and getElementsByClassName

You need to pick the appropriate tool for any given task.

(In the above, for querySelector read querySelector / querySelectorAll).

Quentin
  • 857,932
  • 118
  • 1,152
  • 1,264
47

The functions getElementById and getElementsByClassName are very specific, while querySelector and querySelectorAll are more elaborate. My guess is that they will actually have a worse performance.

Also, you need to check for the support of each function in the browsers you are targetting. The newer it is, the higher probability of lack of support or the function being "buggy".

Thiago Negri
  • 5,133
  • 2
  • 26
  • 39
  • @thomas your link is down. Is there a working link anywhere? – user5508297 Aug 04 '16 at 22:11
  • 8
    There are several archived versions: https://web.archive.org/web/20160108040024/http://jsperf.com/getelementbyid-vs-queryselector But the test is actually very old (2010), so the result might be very different with more modern engines. – thomas Aug 05 '16 at 09:38
  • 7
    The archived page actually is dynamic and allows you to re-run the test on your current browser. querySelectorAll is still slower by reportedly about 37% on my browser. (Chrome 71 - https://vgy.me/TwGL3o.png) It's also worth noting that getElementById returns a live result, meaning that if you change the DOM , the change will be reflected by the result obtained by getElementByID (if in scope) whereas the nodelist returned by querySelectorAll is a snapshot, e.g. as things were at the time the call was made, the result will not reflect subsequent changes to the DOM. – W.Prins Feb 06 '19 at 15:25
  • `nodelist ... is not live` can you provide documentation for that? @W.Prins both methods return the `Element` type. – Maximilian Burszley Dec 30 '19 at 19:06
  • Ah, I see I made a typo, please accept my apologies! I should have written "getElementsByClassName" where I wrote "getElementByID", e.g. it is getElementsByClassName (and similar) which returns a live resultset". Indeed both getElementsByClassName and querySelectorAll returns a NodeList, but in the former case it's live, and in the latter it's a snapshot. – W.Prins Jan 20 '20 at 22:29
  • This being live in case of GetElementsByClassName is described here: https://www.w3.org/TR/2008/WD-html5-20080610/dom.html#getelementsbyclassname Elsewhere (in https://www.w3.org/TR/selectors-api/#queryselectorall) it is written: "The NodeList object returned by the querySelectorAll() method must be static, not live ([DOM-LEVEL-3-CORE], section 1.1.1). Subsequent changes to the structure of the underlying document must not be reflected in the NodeList object." – W.Prins Jan 20 '20 at 22:30