Javascript NodeList

DOM nodeLists sind keine Arrays

querySelectorAll gibt eine statische Liste von Elementen (NodeList) zurück, die beim Löschen oder Einfügen neuer Elemente ohne Update bleibt.

Jede NodeList hat eine length-Eigenschaft, einen Index, der bei 0 beginnt, und der Zugriff auf einzelne Elemente funktioniert wie bei einem Array.

18-12-15 SITEMAP CSS HTML JS Basis JS Web Tutorial SVG

Javascript NodeLists sind keine Arrays

NodeLists sind eng mit Javascript Arrays verwandt, aber ihnen fehlen viele Methoden von Arrays wie valueOf, array push und array pop oder array join.

Trotzdem stehen für eine NodeList aus querySelectorAll gut ein halbes Dutzend Alternativen für die Iteration über die Elemente zur Verfügung.

Demo-Bild Cup
Demo-Bild Buch
Demo-Bild Feder

querySelectorAll und for-Loop

Die gute alte schrittweise for-Schleife: Das ist die älteste Technik, nicht so elegant wie neuere Methoden, aber unterstützt von allen Browsern und eine der schnellsten.

const nodes = document.querySelectorAll(".node");
for (let i=0; i < nodes.length; i++) {
  console.log ("title " + nodes[i].getAttribute("title"));
}

Ein einzelnes Element fischt man mit dem Index aus der NodeList – nicht anders als bei einem Array.

let book = nodes[1];

querySelectorAll mit for of

Eigentlich ist for of nur eine Erweiterung des normalen for-Loops aus ES1. for of läuft über Strings, Arrays und NodeList. Wird von den immergrünen Browsern unterstützt, aber nicht von IE11 und älter.

for (let node of nodes) {
   //console.log (node.innerHTML);
}

Nodelists mit forEach

Die modernen Browser bis auf IE11 unterstützen forEach auch auf NodeLists (Polyfill für forEach in NodeLists mit IE11) auf Github.

forEach und for of sind ausdrucksvoller, besser lesbar im Script und forEach überspringt Löcher in sparse Arrays.

Donut Toast Melone
const elements = document.querySelectorAll (".nodelist img");

elements.forEach (function(img, index) {
   img.setAttribute ("style","border:2px solid gainsboro;margin:4px");
});

spread

Die Spread-Syntax für Arrays wandelt eine NodeList in ein Array um und eröffnet dem NodeList von querySelectorAll das forEach für Arrays.

let items = document.querySelectorAll(".node");
[...items].forEach((item) => {
	console.dir(item);
});

Dynamische / statische NodeList

Die älteren DOM-Methoden getElementsByClassName, getElementsByTagName und getElementsByName liefern eine ähnliche Liste, allerdings als dynamische HTMLCollection. Das dynamische an der HTMLCollection: Wenn neue Elemente in die Sammlung eingefügt oder Elemente gelöscht werden, ändert sich auch die Liste.

Dynamische NodeLists haben ihre eigenen Vorteile gegenüber Arrays: Sie haben ein automatisches Update, wenn neue Elemente in das DOM eingefügt oder Elemente aus dem Dokument gelöscht werden. querySelectorAll gibt eine statische NodeList zurück, keine dynamische HTMLCollection mit Auto-Update.

let nodelist = document.querySelectorAll(".node");
let collection = document.getElementsByClassName("node");

let nodelistLength = nodelist.length;       => 3
let collectionLength = collection.length;   => 3

Wenn ein neues Elemente eingefügt wird:

let cat = document.createElement("div");
cat.classList.add("node");
document.querySelector(".noderow").appendChild(cat);

console.log ( nodelist.length );    => 3
console.log ( collection.length );  => 4

NodeList oder HTMLCollection

Sowohl Collections als auch Nodelists sind Sammlungen oder Auswahlen von DOM-Nodes. Während eine NodeList aus jeder Art von Knoten bestehen kann, enthält eine HTMLCollection nur Element Nodes – Elementknoten.

Neben der Frage statisch oder dynamisch? unterscheiden sich NodeList und HTMLCollection durch ihre Methoden. Ob eine Liste, die von einer der Sammel-Methoden zurückgegeben wird, eine Node List oder eine HTML Collection ist, stellt die Abfrage nach dem Constructor fest.

console.log ( document.querySelectorAll(".node").constructor.name);         => NodeList
console.log ( document.getElementsByClassName("node").constructor.name);   => HTMLCollection
console.log ( document.querySelector(".noderow").children.constructor.name);     => HTMLCollection
console.log ( document.querySelector(".noderow").childNodes.constructor.name);   => NodeList
getElementsByClassName () HTMLCollection live
getElementsByTagName () HTMLCollection live
childNodes () NodeList nicht live
children () HTMLCollection live
getElementsByName () HTMLCollection live
querySelectorAll () NodeList nicht live

NodeList-Methoden

NodeList.item ( i )
Element der NodeList am Index i
NodeList.entries ()
Elemente der Nodelist
NodeList.forEach ()
Iteriert über alle Elemente der NodeList
NodeList.keys ()
Schlüssel, Index der Elemente
NodeList.values ()
Object Array Iterator

Die Methoden entries(), keys() und values() geben einen Iterator zurück. Der Iterator kam mit ES2015 - IE11 und älter bleiben außen vor.

const nodes = document.querySelectorAll(".node");
for (const node of nodes.entries()) {
	console.log('node entries: ', node);
};

for (let key of nodes.keys()) {
	console.log ("keys " + key);
}

console.log (nodes.item(2) );

Array.from: NodeList zu Array mit ES 2015

Array.from erzeugt ein Array aus Array-ähnlichen Objekten und wird die einfachste Technik, um ein Array aus einer NodeList zu generieren.

Damit lassen sich Array-Methoden wie array.map () und array.filter () auch auf NodeLists und HTML-Collections nutzen.

<div class="gallery">
	<div data-img="img/scene1-s.jpg"></div>
	<div data-img="img/scene2-s.jpg"></div>
	<div data-img="img/scene3-s.jpg"></div>
	<div data-img="img/scene4-s.jpg"></div>
</div>
Nähzeug
Stoffmuster
Serviette
Mango
let divs = Array.from(document.querySelectorAll(".gallery div"));

let gallery = divs.map (function (item) {
	item.innerHTML = "<img src='" + item.getAttribute("data-img") + "'>";
	return item.getAttribute("data-img");
})
console.log (gallery); // enthält jetzt die URLs der Bilder

gallery.forEach(function (elem) {
	document.querySelector("#letta").innerHTML += elem ;
});



		

NodeList zu Array (legacy – alte Browser)

Für Browser, die Array.from noch nicht unterstützen (z.B. IE11), gibt es Tipps von allen Seiten in jeglicher Couleur.

ECMAScript 6 compatibility shims for legacy JavaScript engines