Unterschied zwischen HTMLCollection, NodeLists und Arrays von Objekten

92

Ich war immer verwirrt zwischen HTMLCollections, Objekten und Arrays, wenn es um DOM geht. Zum Beispiel...

  1. Was ist der Unterschied zwischen document.getElementsByTagName("td")und $("td")?
  2. $("#myTable") und $("td") sind Objekte (jQuery-Objekte). Warum zeigt console.log auch das Array von DOM-Elementen neben sich an, und sind sie keine Objekte und kein Array?
  3. Worum geht es in den schwer fassbaren "NodeLists" und wie wähle ich eine aus?

Bitte geben Sie auch eine Interpretation des folgenden Skripts an.

Danke dir

[123,"abc",321,"cba"]=[123,"abc",321,"cba"]
{123:123,abc:"abc",321:321,cba:"cba"}=Object { 123=123, abc="abc", 321=321, more...}
Node= Node { ELEMENT_NODE=1, ATTRIBUTE_NODE=2, TEXT_NODE=3, more...}
document.links= HTMLCollection[a #, a #]
document.getElementById("myTable")= <table id="myTable">
document.getElementsByClassName("myRow")= HTMLCollection[tr.myRow, tr.myRow]
document.getElementsByTagName("td")= HTMLCollection[td, td, td, td]
$("#myTable")= Object[table#myTable]
$("td")= Object[td, td, td, td]


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 
<html xmlns="http://www.w3.org/1999/xhtml"> 
    <head> 
        <meta http-equiv="content-type" content="text/html; charset=ISO-8859-1" /> 
        <title>Collections?</title>  
        <script src="http://code.jquery.com/jquery-latest.js" type="text/javascript"></script> 
        <script type="text/javascript">
            $(function(){
                console.log('[123,"abc",321,"cba"]=',[123,"abc",321,"cba"]);
                console.log('{123:123,abc:"abc",321:321,cba:"cba"}=',{123:123,abc:"abc",321:321,cba:"cba"});
                console.log('Node=',Node);
                console.log('document.links=',document.links);
                console.log('document.getElementById("myTable")=',document.getElementById("myTable"));
                console.log('document.getElementsByClassName("myRow")=',document.getElementsByClassName("myRow"))
                console.log('document.getElementsByTagName("td")=',document.getElementsByTagName("td"));
                console.log('$("#myTable")=',$("#myTable"));
                console.log('$("td")=',$("td"));
            });
        </script>
    </head>

    <body>
        <a href="#">Link1</a>
        <a href="#">Link2</a>
        <table id="myTable">
            <tr class="myRow"><td>td11</td><td>td12</td></tr>
            <tr class="myRow"><td>td21</td><td>td22</td></tr>
        </table>
    </body> 
</html>
user1032531
quelle
Ich denke, ich könnte Folgendes für die Nachwelt hinzufügen. (a) In modernem JavaScript wäre ein besserer Vergleich zwischen document.querySelectorAll('td')und $('td'). (b) Der grundlegende Unterschied besteht darin, dass jQuery mit einem eigenen Objekttyp arbeitet, der unter anderem eine nummerierte Sammlung von HTML-Elementen enthält. Diese Auflistung ist keine der oben genannten, und das jQuery-Objekt ist im Wesentlichen ein Wrapper um die wahren DOM-Elemente.
Manngo

Antworten:

112

Zuerst werde ich den Unterschied zwischen NodeListund erklären HTMLCollection.

Beide Schnittstellen sind Sammlungen von DOM-Knoten. Sie unterscheiden sich in den von ihnen bereitgestellten Methoden und in der Art der Knoten, die sie enthalten können. Während a NodeListeinen beliebigen Knotentyp enthalten kann, HTMLCollectionsoll a nur Elementknoten enthalten.
An HTMLCollectionbietet die gleichen Methoden wie a NodeListund zusätzlich eine aufgerufene MethodenamedItem .

Sammlungen werden immer verwendet, wenn der Zugriff auf mehrere Knoten bereitgestellt werden muss, z. B. geben die meisten Auswahlmethoden (z. B. getElementsByTagName) mehrere Knoten zurück oder erhalten einen Verweis auf alle untergeordneten Knoten (z.element.childNodes ).

Weitere Informationen finden Sie in der DOM4-Spezifikation - Sammlungen .

Was ist der Unterschied zwischen document.getElementsByTagName("td")und $("td")?

getElementsByTagNameist die Methode der DOM-Schnittstelle. Es akzeptiert einen Tag-Namen als Eingabe und gibt ein zurück HTMLCollection(siehe DOM4-Spezifikation ).

$("td")ist vermutlich jQuery. Es akzeptiert jeden gültigen CSS / jQuery-Selektor und gibt ein jQuery-Objekt zurück.

Der größte Unterschied zwischen Standard-DOM-Sammlungen und jQuery-Auswahlen besteht darin, dass DOM-Sammlungen normalerweise live sind (nicht alle Methoden geben jedoch eine Live-Sammlung zurück), dh Änderungen am DOM werden in den Sammlungen wiedergegeben, wenn sie betroffen sind. Sie sind wie eine Ansicht des DOM-Baums, während jQuery-Auswahlen Momentaufnahmen des DOM-Baums in dem Moment sind, in dem die Funktion aufgerufen wurde.

Warum zeigt console.log auch das Array von DOM-Elementen neben sich an, und sind sie keine Objekte und kein Array?

jQuery-Objekte sind Array-ähnliche Objekte, dh sie haben numerische Eigenschaften und eine lengthEigenschaft (denken Sie daran, dass Arrays nur Objekte selbst sind). Browser neigen dazu, Arrays und Array-ähnliche Objekte auf besondere Weise anzuzeigen, wie z [ ... , ... , ... ].

Worum geht es in den schwer fassbaren "NodeLists" und wie wähle ich eine aus?

Siehe den ersten Teil meiner Antwort. Sie können s nicht auswählen NodeList , sie sind das Ergebnis einer Auswahl.

Soweit ich weiß, gibt es nicht einmal eine Möglichkeit, NodeLists programmgesteuert zu erstellen (dh ein leeres zu erstellen und später Knoten hinzuzufügen), sondern sie werden nur von einigen DOM-Methoden / -Eigenschaften zurückgegeben.

Felix Kling
quelle
1
@ user1032531: Wenn Sie Änderungen an einem der ausgewählten DOM-Elemente vornehmen (z. B. ein untergeordnetes Element hinzufügen), wird die Änderung natürlich angezeigt, da es sich um ein und dasselbe DOM-Element handelt. Wenn Sie jedoch alle tdElemente ausgewählt haben und später ein neues tdElement hinzufügen, wird die Auswahl nicht automatisch aktualisiert, um das neue Element zu enthalten.
Felix Kling
2
@FelixKling: Du solltest erwähnen, dass nicht alle NodeLists live sind.
Bergi
2
Ich wünschte, sie
wären
7
Es scheint auch, dass Methoden "Schlüssel", "Einträge" und "für jeden" in NodeList vorhanden sind, aber in HTMLCollection fehlen
Krzysztof Grzybek
2
@KrzysztofGrzybek Das stimmt und es ist super nervig. Warum zum Teufel hat einer von ihnen .forEach()und der andere nicht?
Robo Robok
29

0. Was ist der Unterschied zwischen an HTMLCollectionund a NodeList?

Hier sind einige Definitionen für Sie.

DOM Level 1 Spec - Verschiedene Objektdefinitionen :

Schnittstelle HTMLCollection

Eine HTMLCollection ist eine Liste von Knoten. Auf einen einzelnen Knoten kann entweder über den Ordnungsindex oder über die Namen- oder ID-Attribute des Knotens zugegriffen werden. Hinweis: Es wird davon ausgegangen, dass Sammlungen im HTML-DOM live sind. Dies bedeutet, dass sie automatisch aktualisiert werden, wenn das zugrunde liegende Dokument geändert wird.

DOM Level 3 Spec - NodeList

Schnittstellen-NodeList

Die NodeList-Schnittstelle bietet die Abstraktion einer geordneten Sammlung von Knoten, ohne zu definieren oder einzuschränken, wie diese Sammlung implementiert wird. NodeList-Objekte im DOM sind live.

Auf die Elemente in der NodeList kann über einen integralen Index ab 0 zugegriffen werden.

Sie können also beide Live-Daten enthalten, was bedeutet, dass das DOM aktualisiert wird, wenn ihre Werte dies tun. Sie enthalten auch andere Funktionen.

Sie werden feststellen, dass das tableDOM-Element sowohl a childNodes NodeList[2]als auch a enthält , wenn Sie die Konsole überprüfen, wenn Sie Ihre Skripte ausführen children HTMLCollection[1]. Warum sind sie anders? Da HTMLCollectionNodeList nur Elementknoten enthalten kann, enthält es auch einen Textknoten.

Geben Sie hier die Bildbeschreibung ein

1. Was ist der Unterschied zwischen document.getElementsByTagName("td")und $("td")?

document.getElementsByTagName("td")ein Array von DOM - Elemente zurückkehrt (a NodeList), $("td")wird ein jQuery Objekt aufgerufen , die die Elemente aus hat document.getElementsByTagName("td")auf seine Eigenschaften 0, 1,2 usw. Der Hauptunterschied ist , dass das jQuery Objekt ein wenig langsamer ist abzurufen , sondern gibt Zugang zu allen praktisch jQuery-Funktionen.

2. $("#myTable")und $("td")sind Objekte ( jQueryObjekte). Warum istconsole.log neben ihnen auch das Array der DOM-Elemente angezeigt, und sind sie keine Objekte und kein Array?

Sie sind Objekte mit ihren Eigenschaften 0, 1, 2etc. Satz auf die DOM - Elemente. Hier ist ein einfaches Beispiel: wie es funktioniert:

jsFiddle

    var a = {
        1: "first",
        2: "second"
    }
    alert(a[1]);

3. Worum geht es in den schwer fassbaren "NodeLists" und wie wähle ich eine aus?

Sie haben sie in Ihrem Code abgerufen getElementsByClassNameund getElementsByTagNamebeide geben NodeLists zurück

NodeList

Daniel Imms
quelle
Wie haben Sie das DOM in Ihrer dritten Antwort angezeigt? Vielen Dank!
user1032531
@ user1032531 das sind die Chrome-Entwicklungstools. Übrigens habe ich den Anfang der Antwort aktualisiert.
Daniel Imms
Das Array-ähnliche Protokoll ist meistens ein Ergebnis der lengthEigenschaft, nicht der numerischen Eigenschaftsnamen. Und was hat Ihr Beispiel für die Alarmierung einer Zeichenfolge damit zu tun console.log?
Bergi
Das zeigte, wie Sie numerische Eigenschaften für Objekte haben können. Ich versuche die Fakten zu betonen, dass es sich um Objekte handelt, nicht um Arrays.
Daniel Imms
9

Zusätzliche Anmerkung

Was ist der Unterschied zwischen einer HTMLCollection und einer NodeList?

Eine HTMLCollection enthält nur Elementknoten ( Tags ) und eine NodeList enthält alle Knoten .

Es gibt vier Knotentypen:

  1. Elementknoten
  2. Attributknoten
  3. Textknoten
  4. Kommentarknoten

nodeTypes

Leerzeichen in Elementen werden als Text und Text als Knoten betrachtet.

Folgendes berücksichtigen:

<ul id="myList">
  <!-- List items -->
  <li>List item 1</li> 
  <li>List item 2</li>
  <li>List item 3</li>
  <li>List item 4</li>
  <li>List item 5</li>
</ul>

Leerzeichen: <ul id="myList"> <li>List item</li></ul>

Kein Leerzeichen: <ul id="myList"><li>List item</li></ul>

Unterschied zwischen HTMLCollection und einer NodeList

Sonne
quelle
2

$("td")ist ein erweitertes jQuery-Objekt und verfügt über jQuery-Methoden. Es gibt ein jquery-Objekt zurück, das ein Array von HTML-Objekten enthält. document.getElementsByTagName("td")ist die Raw-JS-Methode und gibt NodeList zurück. Siehe diesen Artikel

Karaxuna
quelle
Danke Karaxuna. Ja, ich hatte mir diesen Artikel angesehen. Ich weiß nicht, ob es geholfen hat, aber ich habe definitiv mehr Fragen gestellt :)
user1032531
Danke @karaxuna. Nützlicher Artikel, sehr gut erklärt.
Giuseppe
0

Die NodeList- Objekte sind Sammlungen von Knoten, die beispielsweise von x zurückgegeben werden. childNodes- Eigenschaft oder document.querySelectorAll () -Methode. In einigen Fällen ist der NodeList Live , was bedeutet , dass Änderungen in dem DOM automatisch die Sammlung aktualisieren! Zum Beispiel ist Node.childNodes live:

var c = parent.childNodes; //assume c.length is 2
parent.appendChild(document.createElement('div'));
//now c.length is 3, despite the `c` variable is assigned before appendChild()!!
//so, do not cache the list's length in a loop.

In einigen anderen Fällen ist die NodeList jedoch statisch , wobei Änderungen im DOM den Inhalt der Sammlung nicht beeinflussen. querySelectorAll () gibt eine statische NodeList zurück.

Die HTMLCollection ist eine Live- und geordnete Sammlung von Elementen (sie wird automatisch aktualisiert, wenn das zugrunde liegende Dokument geändert wird). Es kann aufgrund der Eigenschaften wie als seine Kinder oder Methoden wie als document.getElementsByTagName () , und konnte nur Htmlelement des als ihre Einzelteile.

HTMLCollection macht seine Mitglieder auch direkt als Eigenschaften sowohl nach Name als auch nach Index verfügbar:

var f = document.forms; // this is an HTMLCollection
f[0] === f.item(0) === f.myForm //assume first form id is 'myForm'

Das HTMLElement ist nur eine Art von Knoten:

Knoten << HTMLElement-Vererbung

Der Knoten kann verschiedene Typen haben . Die wichtigsten sind wie folgt:

  • Element (1): Ein Elementknoten wie <p>oder <div>.
  • Attribut (2): Ein Attribut eines Elements. Die Elementattribute implementieren die Knotenschnittstelle in der DOM4-Spezifikation nicht mehr!
  • Text (3): Der tatsächliche Text des Elements oder Attributs.
  • Kommentar (8): Ein Kommentarknoten.
  • Dokument (9): Ein Dokumentknoten.

Ein großer Unterschied besteht also darin, dass HTMLCollection nur HTMLElements enthält, NodeList jedoch auch Kommentare, Leerzeichen (Zeilenumbruchzeichen, Leerzeichen ..) usw. enthält. Überprüfen Sie dies wie im folgenden Snippet:

function printList(x, title) {
  console.log("\r\nprinting "+title+" (length="+x.length+"):");
  for(var i=0; i<x.length; i++) {
    console.log("  "+i+":"+x[i]);
  }
}

var elems = document.body.children; //HTMLCollection
var nodes = document.body.childNodes; //NodeList

printList(elems, "children [HTMLCollection]");
printList(nodes, "childNodes [NodeList]");
<div>para 1</div><!-- MyComment -->
<div>para 2</div>

Sowohl HTMLCollection und NodeList enthalten die Länge Eigenschaft , die Sie verwenden können , Schleife über ihre Produkte. Verwenden Sie nicht für ... in oder für jedes ... in, um die Elemente in NodeLists aufzulisten, da sie auch deren Länge und Elementeigenschaften auflisten und Fehler verursachen, wenn Ihr Skript davon ausgeht, dass es sich nur um Elementobjekte handelt. Es ist auch nicht garantiert, dass for..in die Immobilien in einer bestimmten Reihenfolge besucht.

for (var i = 0; i < myNodeList.length; i++) {
  var item = myNodeList[i];
}
S. Serpooshan
quelle
0

Es wurde bereits viel gesagt, aber ich dachte an eine zusammengefasstere Version der Antwort mit einem Beispiel, um die Unterschiede zwischen zu erklären HTMLCollectionund NodeListwürde helfen.

Knotentypen in DOM

  • Es gibt 12 verschiedene Knotentypen, die untergeordnete Knoten verschiedener Knotentypen haben können:

Geben Sie hier die Bildbeschreibung ein

  • Wir können die folgenden drei Eigenschaften verwenden, um Knoten in DOM zu untersuchen und abzufragen:

    • nodeType Eigentum
    • nodeName Eigentum
    • nodeValue Eigentum
  • Das nodeType Eigenschaft gibt den Knotentyp als Nummer des angegebenen Knotens zurück.

    • Wenn der Knoten ein Elementknoten ist, wird der nodeType Eigenschaft 1 zurück .
    • Wenn der Knoten ein Attributknoten ist, wird der nodeType Eigenschaft 2 zurück .
    • Wenn der Knoten ein Textknoten ist, wird der nodeType Eigenschaft 3 zurück .
    • Wenn der Knoten ein Kommentarknoten ist, wird der nodeType Eigenschaft 8 zurück .
    • Diese Eigenschaft ist schreibgeschützt.

HTMLCollection vs NodeList

Geben Sie hier die Bildbeschreibung ein

Wir können die Unterschiede zwischen HTMLCollectionund anhand NodeListdes folgenden Beispiels klarer verstehen . Bitte versuchen Sie, die Ausgaben in Ihrer eigenen Browserkonsole zu überprüfen, um ein besseres Verständnis zu erhalten.

<ul>
  <li>foo</li>
  <li>bar</li>
  <li>bar</li>
</ul>
// retrieve element using querySelectorAll
const listItems_querySelector = document.querySelectorAll('li');
console.log('querySelector', listItems_querySelector);

// retrieve element using childNodes
const list  = document.querySelector('ul')
const listItems_childNodes = list.childNodes;
console.log('childNodes', listItems_childNodes);
const listItems_children = list.children;
console.log('children', listItems_children);

const listItems_getElementsByTagName = document.getElementsByTagName('li');
console.log('getElementsByTagName', listItems_getElementsByTagName);

console.log('*************************');
console.log('add one list item');
console.log('*************************');
list.appendChild(document.createElement('li'));

console.log('querySelector', listItems_querySelector);
console.log('childNodes', listItems_childNodes);
console.log('children', listItems_children);
console.log('getElementsByTagName', listItems_getElementsByTagName);

console.log('*************************');
console.log('add one more list item');
console.log('*************************');
listItems_getElementsByTagName[0].parentNode.appendChild(document.createElement('li'));

console.log('querySelector', listItems_querySelector);
console.log('childNodes', listItems_childNodes);
console.log('children', listItems_children);
console.log('getElementsByTagName', listItems_getElementsByTagName); 
Shraddha
quelle