Hallo Gunnar,
wobei gesagt werden muss, dass getElementById('a') dasselbe tut wie querySelector('#a').
Auf Ebene von Document oder DocumentFragment: Ja.
Auf Ebene von Element: Nein.
Denn getElementById
ist eine Methode von NonElementParentNode
, ein Mixin, das von Document
und DocumentFragment eingebunden wird. Hingegen ist querySelector
eine Methode von ParentNode
, ein Mixin, das von Document
, DocumentFragment
und Element
inkludiert wird.
Als Ergebnis sucht getElementById immer global im Dokument oder Fragment, während querySelector auf einen Element aufgerufen werden kann und dann auf dessen Scope beschränkt ist.
Ob das merkliche Performance-Auswirkungen hat, glaube ich nicht. Die CSS Selectorengine dürfte jegliche Optimierung erhalten haben, die man sich nur vorstellen kann. In riesigen DOMs könnte das Suchen in einem kleineren Teilbaum vielleicht effizienter sein. Es könnte aber auch sein, dass getElementById durch eine Hashmap optimiert wird. Müsste man testen und messen.
Funktionale Auswirkungen können sich ergeben,
- wenn ich den Selektor #a im Scope eines bestimmten Elements suche, aber das das Element mit der ID
a
ist kein Kind des Scope-Elements, sondern anderswo im DOM (Parent, Sibling, x-th Cousin y-th removed - frag einen Hobbit…) - wenn ich ein ungültiges DOM mit nicht-eindeutigen IDs erstelle und das Problem damit „löse“, dass ich die uneindeutigen IDs im passenden Teilbaum suche, in dem sie eindeutig sind. Oder merkwürdige Abfragen wie
querySelectorAll("#a")
oderquerySelector(".t #a")
fabriziere.
Das trifft auf die anderen Methoden nicht zu; die könnte man unter Sonstiges verbuchen.
Muss man vielleicht auch im Nebensatz erwähnen, dass querySelectorAll eine statische Nodelist liefert, aber getElementsByTagName, getElementsByClassName und children eine live HTMLCollection, getElementsByName und childNodes jedoch eine live NodeList? Warum getElementsByName eine NodeList liefert, die beiden anderen getElements-Methoden hingegen eine HTMLCollection, ist vermutlich ein Artefakt der Browserkriege, aber es ist schon eine Inkonsistenz zum Verzeifeln.
Hantieren mit live collections ist kritisch wenn man das DOM verändert. Ich würde auch wetten, dass ihre Verwendung Tempo kostet, weil sie bei jeder Verwendung neu erstellt werden müssen oder sie das DOM ständig auf Änderungen belauschen müssen. Hinzu kommt, dass man der NodeList-Schnittstelle die forEach-Methode spendiert hat und die Iterator-Quellen entries, keys und values, das würde ich als deutlichen Vorteil von querySelectorAll darstellen.
Oh. Ups. HTMLCollection implementiert den Iterator neuerdings auch?! Is ja heiß…
Gibt es Fälle, wo man unbedingt eine live-Collection aus Elementen braucht (von children
und childNodes
abgesehen)?
Interessant ist auch dieser Stackoverflow-Beitrag von 2022, der etwas zur Historie der arrayoiden Listentypen im DOM verrät.
Rolf
sumpsi - posui - obstruxi