Differenza tra HTMLCollection, NodeLists e array di oggetti


94

Sono sempre stato confuso tra HTMLCollections, oggetti e array quando si tratta di DOM. Per esempio...

  1. Qual'è la differenza tra document.getElementsByTagName("td")e $("td")?
  2. $("#myTable")e $("td")sono oggetti (oggetti jQuery). Perché console.log mostra anche l'array di elementi DOM accanto a loro e non sono oggetti e non un array?
  3. In cosa consistono gli elusivi "NodeLists" e come selezionarne uno?

Fornisci anche un'interpretazione dello script seguente.

Grazie

[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>

Penso di poter aggiungere quanto segue per i posteri. (a) Nel JavaScript moderno, un confronto migliore sarebbe tra document.querySelectorAll('td')e $('td'). (b) La differenza fondamentale è che jQuery funziona con il proprio tipo di oggetto che contiene, tra le altre cose, una raccolta numerata di elementi HTML; questa raccolta non è nessuna delle precedenti e l'oggetto jQuery è essenzialmente un wrapper attorno ai veri elementi DOM.
Manngo

Risposte:


113

Per prima cosa spiegherò la differenza tra NodeListe HTMLCollection.

Entrambe le interfacce sono raccolte di nodi DOM. Differiscono nei metodi che forniscono e nel tipo di nodi che possono contenere. Mentre a NodeListpuò contenere qualsiasi tipo di nodo, an HTMLCollectiondovrebbe contenere solo nodi Element.
An HTMLCollectionfornisce gli stessi metodi di a NodeListe in aggiunta un metodo chiamato namedItem.

Le raccolte vengono sempre utilizzate quando è necessario fornire l'accesso a più nodi, ad esempio la maggior parte dei metodi di selezione (come getElementsByTagName) restituiscono più nodi o ottengono un riferimento a tutti i figli ( element.childNodes).

Per ulteriori informazioni, dai un'occhiata alla specifica DOM4 - Collezioni .

Qual'è la differenza tra document.getElementsByTagName("td")e $("td")?

getElementsByTagNameè il metodo dell'interfaccia DOM. Accetta un nome di tag come input e restituisce un HTMLCollection(vedere la specifica DOM4 ).

$("td")è presumibilmente jQuery. Accetta qualsiasi selettore CSS / jQuery valido e restituisce un oggetto jQuery.

La differenza maggiore tra le raccolte DOM standard e le selezioni jQuery è che le raccolte DOM sono in genere attive (non tutti i metodi restituiscono una raccolta attiva, tuttavia), ovvero qualsiasi modifica al DOM si riflette nelle raccolte se sono interessate. Sono come una vista sull'albero DOM, mentre le selezioni jQuery sono istantanee dell'albero DOM nel momento in cui è stata chiamata la funzione.

Perché console.log mostra anche l'array di elementi DOM accanto a loro e non sono oggetti e non un array?

Gli oggetti jQuery sono oggetti simili ad array , cioè hanno proprietà numeriche e una lengthproprietà (tieni presente che gli array sono solo oggetti stessi). I browser tendono a visualizzare array e oggetti simili a array in un modo speciale, come [ ... , ... , ... ].

In cosa consistono gli elusivi "NodeLists" e come selezionarne uno?

Vedi la prima parte della mia risposta. Non è possibile selezionare i messaggi di posta NodeList elettronica, sono il risultato di una selezione.

Per quanto ne so non c'è nemmeno un modo per creare NodeLists programmaticamente (cioè crearne uno vuoto e aggiungere nodi in seguito), vengono restituiti solo da alcuni metodi / proprietà DOM.


2
@ user1032531: Bene, se apporti una qualsiasi modifica a uno degli elementi DOM selezionati (ad es. aggiungendo un figlio), ovviamente vedrai la modifica poiché è lo stesso elemento DOM. Ma, supponendo che tu abbia selezionato tutti gli tdelementi, l'aggiunta di un nuovo tdelemento in seguito non aggiornerà automaticamente la selezione per contenere il nuovo elemento.
Felix Kling

2
@FelixKling: Dovresti menzionare che non tutti NodeListi messaggi sono live.
Bergi

2
Vorrei che fossero tutti array
SuperUberDuper

7
Sembra anche che i metodi "chiavi", "voci" e "forEach" siano presenti in NodeList, ma mancanti in HTMLCollection
Krzysztof Grzybek

2
@KrzysztofGrzybek Esatto ed è super fastidioso. Perché diavolo uno di loro ha .forEach()e l'altro no?
Robo Robok

30

0. Qual è la differenza tra an HTMLCollectione a NodeList?

Ecco alcune definizioni per te.

Specifiche DOM livello 1 - Definizioni di oggetti vari :

Interfaccia HTMLCollection

Una HTMLCollection è un elenco di nodi. È possibile accedere a un singolo nodo tramite l'indice ordinale o il nome del nodo o gli attributi id. Nota: si presume che le raccolte nel DOM HTML siano attive, il che significa che vengono aggiornate automaticamente quando il documento sottostante viene modificato.

Specifiche DOM livello 3 - NodeList

Interface NodeList

L'interfaccia NodeList fornisce l'astrazione di una raccolta ordinata di nodi, senza definire o vincolare la modalità di implementazione di questa raccolta. Gli oggetti NodeList nel DOM sono attivi.

Gli elementi nella NodeList sono accessibili tramite un indice integrale, a partire da 0.

Quindi possono entrambi contenere dati in tempo reale, il che significa che il DOM si aggiornerà quando i loro valori lo faranno. Contengono anche un diverso insieme di funzioni.

Noterai se ispezioni la console se esegui i tuoi script che l' tableelemento DOM contiene sia a childNodes NodeList[2]che a children HTMLCollection[1]. Perché sono differenti? Poiché HTMLCollectionpuò contenere solo nodi di elementi, NodeList contiene anche un nodo di testo.

inserisci qui la descrizione dell'immagine

1. Qual è la differenza tra document.getElementsByTagName("td")e $("td")?

document.getElementsByTagName("td")restituisce un array di elementi DOM (a NodeList), $("td")viene chiamato un oggetto jQuery che presenta gli elementi da document.getElementsByTagName("td")sulle sue proprietà 0, 1, 2, ecc La differenza principale è che l'oggetto jQuery è un po 'più lento per recuperare ma dà accesso a tutte le pratico Funzioni jQuery.

2. $("#myTable")e $("td")sono oggetti ( jQueryoggetti). Perché console.logmostra anche l'array di elementi DOM accanto a loro e non sono oggetti e non sono un array?

Sono oggetti con le loro proprietà 0, 1, 2, ecc insieme agli elementi DOM. Ecco un semplice esempio: di come funziona:

jsFiddle

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

3. In cosa consistono gli elusivi "NodeLists" e come selezionarne uno?

Li hai recuperati nel codice getElementsByClassNameed getElementsByTagNameentrambi restituiscono NodeLists

NodeList


Come hai visualizzato il DOM nella tua terza risposta? Grazie!
user1032531

@ user1032531 ovvero gli strumenti di sviluppo di Chrome. A proposito, ho aggiornato l'inizio della risposta.
Daniel Imms

Il log di tipo array è principalmente il risultato della lengthproprietà, non dei nomi delle proprietà numeriche. E con cosa ha a che fare il tuo esempio di avviso di una stringa console.log?
Bergi

Questo mostrava come si possono avere proprietà numeriche sugli oggetti. Sto cercando di sottolineare i fatti che sono oggetti, non array.
Daniel Imms

9

Nota aggiuntiva

Qual è la differenza tra una HTMLCollection e una NodeList?

Una HTMLCollection contiene solo nodi di elementi ( tag ) e una NodeList contiene tutti i nodi .

Esistono quattro tipi di nodo:

  1. nodo dell'elemento
  2. nodo attributo
  3. nodo di testo
  4. nodo di commento

nodeTypes

Gli spazi all'interno degli elementi sono considerati come testo e il testo è considerato come nodi.

Considera quanto segue:

<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>

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

Nessuno spazio bianco: <ul id="myList"><li>List item</li></ul>

Differenza tra HTMLCollection e un NodeList


2

$("td")è un oggetto jQuery esteso e ha metodi jQuery, restituisce un oggetto jquery che contiene un array di oggetti html. document.getElementsByTagName("td")è il metodo js grezzo e restituisce NodeList. Vedi questo articolo


Grazie Karaxuna. Sì, avevo letto quell'articolo. Non so se ha aiutato, ma sicuramente mi ha fatto fare altre domande :)
user1032531

Grazie @karaxuna. Articolo utile, molto ben spiegato.
Giuseppe

0

Gli oggetti NodeList sono raccolte di Node, restituite ad esempio da x. proprietà childNodes o metodo document.querySelectorAll () . In alcuni casi, il NodeList è vivo , il che significa che i cambiamenti nel DOM aggiornare automaticamente la collezione! Ad esempio, 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.

Ma in alcuni altri casi, NodeList è statico , in cui qualsiasi modifica nel DOM non influisce sul contenuto della raccolta. querySelectorAll () restituisce un NodeList statico.

Il HTMLCollection è un vivo e ordinata raccolta di elementi (che si aggiorna automaticamente quando il documento sottostante viene modificato). Può essere il risultato di proprietà come as children o metodi come document.getElementsByTagName () e potrebbe avere solo HTMLElement come elementi.

HTMLCollection espone anche i suoi membri direttamente come proprietà sia per nome che per indice:

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

HTMLElement è solo un tipo di nodi:

Nodo << HTMLElement inheritance

Il nodo può essere di diversi tipi . I più importanti sono i seguenti:

  • element (1): un nodo Element come <p>o <div>.
  • attributo (2): un attributo di un elemento. Gli attributi dell'elemento non implementano più l'interfaccia Node nella specifica DOM4!
  • text (3): il testo effettivo dell'elemento o dell'attributo.
  • comment (8): un nodo di commento.
  • document (9): un nodo del documento.

Quindi, una grande differenza è che HTMLCollection contiene solo HTMLElements ma NodeList contiene anche i commenti, i testi con spazi bianchi (caratteri di ritorno a capo, spazi ..), ecc. Controllalo come nel seguente frammento:

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>

Sia HTMLCollection e NodeList contengono la lunghezza di proprietà è possibile utilizzare per ciclo sopra le loro voci. Non usare per ... in o per ogni ... in per enumerare gli elementi in NodeLists, poiché enumereranno anche la sua lunghezza e le proprietà dell'elemento e causeranno errori se lo script presume che abbia a che fare solo con oggetti elemento. Inoltre, per..in non è garantito che visiti le proprietà in un ordine particolare.

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

0

È già stato detto così tanto, ma ho pensato a una versione più sintetica della risposta con un esempio per spiegare le differenze tra HTMLCollectione NodeListsarebbe stato d'aiuto.

Tipi di nodi in DOM

  • Esistono 12 diversi tipi di nodo, che possono avere figli di vari tipi di nodo:

inserisci qui la descrizione dell'immagine

  • Possiamo utilizzare le seguenti tre proprietà per ispezionare e richiedere informazioni sui nodi nel DOM:

    • nodeType Proprietà
    • nodeName Proprietà
    • nodeValue Proprietà
  • La nodeTypeproprietà restituisce il tipo di nodo, come numero, del nodo specificato.

    • Se il nodo è un nodo elemento, la nodeTypeproprietà restituirà 1 .
    • Se il nodo è un nodo attributo, la nodeTypeproprietà restituirà 2 .
    • Se il nodo è un nodo di testo, la nodeTypeproprietà restituirà 3 .
    • Se il nodo è un nodo di commento, la nodeTypeproprietà restituirà 8 .
    • Questa proprietà è di sola lettura.

HTMLCollection vs NodeList

inserisci qui la descrizione dell'immagine

Possiamo capire le differenze tra HTMLCollectione NodeListpiù chiaramente con il seguente esempio. Per favore, prova a controllare gli output nella tua console del browser per avere una migliore comprensione.

<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); 
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.