Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why doesn't querySelector('#id') map to document.getElementById('id')?

I'm into selectors performance lately, and it's bugging me that the browsers which currently implements the Selectors API don't use document.getElementById when a simple #id is being passed.

The performance penalty is huge, so library authors continue to implement their own way around that.

Any ideas?

like image 378
Ronny Avatar asked Nov 28 '10 19:11

Ronny


People also ask

What does document querySelector (' h1 ') do in Javascript?

The Document method querySelector() returns the first Element within the document that matches the specified selector, or group of selectors. If no matches are found, null is returned.

What can I use instead of querySelector?

The equivalent of the document. querySelector() method in React is using refs. To select an element, set the ref prop on it to the return value of calling the useRef() hook and access the dom element using the current property on the ref , e.g. ref.

Why is my querySelector null?

The "Cannot read property 'querySelector' of null" error occurs for 2 reasons: Calling the querySelector() method on a null value (DOM element that doesn't exist). Inserting the JS script tag above the HTML where the DOM elements are declared.

Is querySelector better than getElementById?

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. You need to pick the appropriate tool for any given task.


2 Answers

After making my comment above, I decided to follow through:

From Node.cpp in the Chromium source

if (strictParsing && inDocument() && querySelectorList.hasOneSelector() && querySelectorList.first()->m_match == CSSSelector::Id) {
    Element* element = document()->getElementById(querySelectorList.first()->m_value);
    if (element && (isDocumentNode() || element->isDescendantOf(this)) && selectorChecker.checkSelector(querySelectorList.first(), element))
        return element;
    return 0;
}

So it does map on getElementById, it is just that parsing the string looking for selectors is an expensive operation.

like image 124
Quentin Avatar answered Oct 08 '22 03:10

Quentin


Tbh. the performance penalty is insignificant... I really doubt you're going to do 100.000 id lookups per second, if you do, then QSA performance is actually the last thing you should look at.

As to why, adding an extra if/else might make id lookups more performant, but then other css selectors will be a fraction (still insignificant) slower. Why optimize QSA to deal with id lookups when there's a specialist method to do exactly that a lot faster anyways.

In any case, browsers are aiming for speed and leaving out stuff like this makes the overall performance charts look a lot better. In this benchmark race it's REALLY about every single millisecond, but for the developers... please be realistic, other benchmarks are more important, QSA performance shouldn't really be a factor anymore.

As for developer convenience, it works, it's still so fast you won't notice it in actual applications (I challenge you to show me where it's IS VISUALLY noticable whilst still being a sane program ;o).

like image 39
BGerrissen Avatar answered Oct 08 '22 05:10

BGerrissen