SELF-Wiki: Was ist das DOM?
Matthias Scharwies
- dom
- javascript
- selfhtml-wiki
Guten Morgen,
hier hatte ich es schon angekündigt: JavaScript und das DOM/Was ist das DOM?
Wir hatten an verschiedenen Stellen nahezu gleichlautende Erklärungen, die ich jetzt zu einem Anfänger-Tutorial zusammengefasst habe:
Die im Wiki vielfach vorkommende Liste der „DOM-Methoden“ würde ich ebenfalls gerne auf den Prüfstand stellen:
Imho würde ich nur die letzten beiden und classList empfehlen. Was meint ihr?
Herzliche Grüße
Matthias Scharwies
@@Matthias Scharwies
- getElementById(): kann auf Elemente zugreifen, die ein dokumentweit eindeutiges id-Attribut enthalten
- getElementsByName(): kann auf Elemente zugreifen, die einen Namen besitzen (er muss nicht unbedingt eindeutig sein)
- getElementsByTagName(): kann auf alle Elemente zugreifen in der Form: "liefere mir das 27. td-Element im Dokument".
?? getElementsByTagName()
liefert alle Elemente dieses Namens. Für das 27. td-Element ist Weiteres erforderlich, was wohl nichts in dieser Übersicht verloren hat.
- querySelector(): gibt das erste Element zurück, das dem angegebenen CSS-Selektor entspricht.
- querySelectorAll(): gibt eine Liste von Elementen zurück, die dem angegebenen CSS-Selektor (auch mehrere, durch Komma getrennte, Angaben möglich) entsprechen
Imho würde ich nur die letzten beiden und classList empfehlen. Was meint ihr?
Ja, mit querySelector()
/querySelectorAll()
hat man ein einheitliches Interface für alle Fälle.
getElementById()
ist so weit verbreitet, dass es Erwähnung verdient, wobei gesagt werden muss, dass getElementById('a')
dasselbe tut wie querySelector('#a')
.
Das trifft auf die anderen Methoden nicht zu; die könnte man unter Sonstiges verbuchen. Einfach sagen, dass es weitere Methoden gibt (getElementsByTagName()
könnte man dabei namentlich erwähnen, muss man aber nicht), die man aber nicht mehr braucht, da man ja jetzt querySelector()
/querySelectorAll()
hat.
Kwakoni Yiquan
Moin Gunnar,
getElementById()
ist so weit verbreitet, dass es Erwähnung verdient, wobei gesagt werden muss, dassgetElementById('a')
dasselbe tut wiequerySelector('#a')
.Das trifft auf die anderen Methoden nicht zu; die könnte man unter Sonstiges verbuchen. Einfach sagen, dass es weitere Methoden gibt (
getElementsByTagName()
könnte man dabei namentlich erwähnen, muss man aber nicht), die man aber nicht mehr braucht, da man ja jetztquerySelector()
/querySelectorAll()
hat.
wie ist denn eigentlich die Performance im Vergleich zwischen den spezifischen Methoden und „query selector“?
Meine Erwartung ist, dass das Parsen des „query strings“ etwas mehr Zeit und Rechenleistung benötigt als schon direkt im DOM den entsprechend Lookup durchzuführen.
Viele Grüße
Robert
Servus!
@@Matthias Scharwies
- getElementById(): kann auf Elemente zugreifen, die ein dokumentweit eindeutiges id-Attribut enthalten
- getElementsByName(): kann auf Elemente zugreifen, die einen Namen besitzen (er muss nicht unbedingt eindeutig sein)
- getElementsByTagName(): kann auf alle Elemente zugreifen in der Form: "liefere mir das 27. td-Element im Dokument".
??
getElementsByTagName()
liefert alle Elemente dieses Namens. Für das 27. td-Element ist Weiteres erforderlich, was wohl nichts in dieser Übersicht verloren hat.
- querySelector(): gibt das erste Element zurück, das dem angegebenen CSS-Selektor entspricht.
- querySelectorAll(): gibt eine Liste von Elementen zurück, die dem angegebenen CSS-Selektor (auch mehrere, durch Komma getrennte, Angaben möglich) entsprechen
Imho würde ich nur die letzten beiden und classList empfehlen. Was meint ihr?
Ja, mit
querySelector()
/querySelectorAll()
hat man ein einheitliches Interface für alle Fälle.
getElementById()
ist so weit verbreitet, dass es Erwähnung verdient, wobei gesagt werden muss, dassgetElementById('a')
dasselbe tut wiequerySelector('#a')
.Das trifft auf die anderen Methoden nicht zu; die könnte man unter Sonstiges verbuchen. Einfach sagen, dass es weitere Methoden gibt (
getElementsByTagName()
könnte man dabei namentlich erwähnen, muss man aber nicht), die man aber nicht mehr braucht, da man ja jetztquerySelector()
/querySelectorAll()
hat.
Ja, danke! Seh' ich auch so!
Herzliche Grüße
Matthias Scharwies
Hallo zusammen,
Ja, mit
querySelector()
/querySelectorAll()
hat man ein einheitliches Interface für alle Fälle.
getElementById()
ist so weit verbreitet, dass es Erwähnung verdient, wobei gesagt werden muss, dassgetElementById('a')
dasselbe tut wiequerySelector('#a')
.Das trifft auf die anderen Methoden nicht zu; die könnte man unter Sonstiges verbuchen. Einfach sagen, dass es weitere Methoden gibt (
getElementsByTagName()
könnte man dabei namentlich erwähnen, muss man aber nicht), die man aber nicht mehr braucht, da man ja jetztquerySelector()
/querySelectorAll()
hat.
Kann man für Neueinsteigende so machen, wobei die Erwähnung von getElementById()
, getElementsByName()
, getElementsByClassName()
, getElementsByTagName()
und (in speziellen Kontexten) getElementsByTagNameNS()
durchaus nützlich sein kann, wenn man es etwa mit älterem Code zutun hat und Anpassungen durchführen möchte.
Erwähnenswert ist aber, dass querySelector()
/ querySelectorAll()
wie andere Elements-Methoden nicht nur auf dem Document- sondern auch auf dem Element-Interface wirken können:
<ul id="spezielle_liste">
<li>Text</li>
<li>Text</li>
<li>Text</li>
</ul>
<script>
const ul = document.querySelector("#spezielle_liste");
const ul_li = ul.querySelectorAll("li");
console.log(ul_li.length); // 3
</script>
Interessanterweise klappt das mittlerweile sogar bei AJAXifizierten Inhalten, also eingelesenen XML-Strukturen. Dort war bisher xmlroot.getElementsByTagName("xmlelement") zielführend(er).
Grüße,
Thomas
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,
a
ist kein Kind des Scope-Elements, sondern anderswo im DOM (Parent, Sibling, x-th Cousin y-th removed - frag einen Hobbit…)querySelectorAll("#a")
oder querySelector(".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