Différence entre HTMLCollection, NodeLists et tableaux d'objets

93

J'ai toujours été confus entre HTMLCollections, objets et tableaux quand il s'agit de DOM. Par exemple...

  1. Quelle est la différence entre document.getElementsByTagName("td") et $("td")?
  2. $("#myTable") et $("td") sont des objets (objets jQuery). Pourquoi console.log affiche-t-il également le tableau des éléments DOM à côté d'eux, et ne sont-ils pas des objets et pas un tableau?
  3. Qu'est-ce que les "NodeLists" insaisissables et comment en sélectionner une?

Veuillez également fournir toute interprétation du script ci-dessous.

Je vous remercie

[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>
utilisateur1032531
la source
Je pense que je pourrais ajouter ce qui suit pour la postérité. (a) En JavaScript moderne, une meilleure comparaison serait entre document.querySelectorAll('td')et $('td'). (b) La différence fondamentale est que jQuery fonctionne avec son propre type d'objet qui contient, entre autres, une collection numérotée d'éléments HTML; cette collection n'est rien de ce qui précède, et l'objet jQuery est essentiellement un wrapper autour des vrais éléments DOM.
Manngo

Réponses:

112

Je vais d'abord expliquer la différence entre NodeListet HTMLCollection.

Les deux interfaces sont des collections de nœuds DOM. Ils diffèrent par les méthodes qu'ils fournissent et par le type de nœuds qu'ils peuvent contenir. Alors que a NodeListpeut contenir n'importe quel type de nœud, an HTMLCollectionest censé ne contenir que des nœuds Elément.
An HTMLCollectionfournit les mêmes méthodes que a NodeListet en plus une méthode appelée namedItem.

Les collections sont toujours utilisées lorsque l'accès doit être fourni à plusieurs nœuds, par exemple, la plupart des méthodes de sélection (telles que getElementsByTagName) retournent plusieurs nœuds ou obtiennent une référence à tous les enfants ( element.childNodes).

Pour plus d'informations, consultez la spécification DOM4 - Collections .

Quelle est la différence entredocument.getElementsByTagName("td") et $("td")?

getElementsByTagNameest la méthode de l'interface DOM. Il accepte un nom de balise comme entrée et renvoie un HTMLCollection(voir la spécification DOM4 ).

$("td")est probablement jQuery. Il accepte tout sélecteur CSS / jQuery valide et renvoie un objet jQuery.

La plus grande différence entre les collections DOM standard et les sélections jQuery est que les collections DOM sont généralement actives (toutes les méthodes ne renvoient cependant pas une collection active), c'est-à-dire que toutes les modifications apportées au DOM sont reflétées dans les collections si elles sont affectées. Ils sont comme une vue sur l'arborescence DOM, tandis que les sélections jQuery sont des instantanés de l'arborescence DOM au moment où la fonction a été appelée.

Pourquoi console.log affiche-t-il également le tableau des éléments DOM à côté d'eux, et ne sont-ils pas des objets et pas un tableau?

Les objets jQuery sont des objets de type tableau , c'est -à- dire qu'ils ont des propriétés numériques et une lengthpropriété (gardez à l'esprit que les tableaux ne sont que des objets eux-mêmes). Les navigateurs ont tendance à afficher les tableaux et les objets de type tableau d'une manière spéciale, comme [ ... , ... , ... ].

Qu'est-ce que les "NodeLists" insaisissables et comment en sélectionner une?

Voir la première partie de ma réponse. Vous ne pouvez pas sélectionner les NodeList s, ils sont le résultat d'une sélection.

Autant que je sache, il n'y a même pas de moyen de créer des NodeLists par programme (c'est-à-dire en créant un vide et en ajoutant des nœuds plus tard), ils ne sont retournés que par certaines méthodes / propriétés DOM.

Félix Kling
la source
2
@ user1032531: Eh bien, si vous apportez une modification à l'un des éléments DOM sélectionnés (par exemple en ajoutant un enfant), alors vous verrez bien sûr la modification puisqu'il s'agit d'un seul et même élément DOM. Mais, en supposant que vous ayez sélectionné tous les tdéléments, l'ajout d'un nouvel tdélément ultérieurement ne mettra pas à jour automatiquement la sélection pour contenir le nouvel élément.
Felix Kling
2
@FelixKling: Vous devez mentionner que tous les NodeLists ne sont pas en ligne.
Bergi
2
Je souhaite qu'ils soient tous des tableaux
SuperUberDuper
7
Il semble aussi que les méthodes "clés", "entrées" et "forEach" soient présentes dans NodeList, mais manquantes dans HTMLCollection
Krzysztof Grzybek
2
@KrzysztofGrzybek C'est vrai et c'est super ennuyeux. Pourquoi diable l'un d'eux a .forEach()et l'autre pas?
Robo Robok
29

0. Quelle est la différence entre un HTMLCollectionet unNodeList ?

Voici quelques définitions pour vous.

Spécification DOM niveau 1 - Définitions d'objets divers :

Interface HTMLCollection

Une HTMLCollection est une liste de nœuds. Un nœud individuel peut être accédé soit par un index ordinal, soit par le nom du nœud ou les attributs id. Remarque: Les collections du DOM HTML sont supposées être actives, ce qui signifie qu'elles sont automatiquement mises à jour lorsque le document sous-jacent est modifié.

Spécification DOM niveau 3 - NodeList

Liste de nœuds d'interface

L'interface NodeList fournit l'abstraction d'une collection ordonnée de nœuds, sans définir ni contraindre la manière dont cette collection est implémentée. Les objets NodeList dans le DOM sont actifs.

Les éléments de la NodeList sont accessibles via un index intégral, à partir de 0.

Ainsi, ils peuvent tous les deux contenir des données en direct, ce qui signifie que le DOM se mettra à jour lorsque leurs valeurs le feront. Ils contiennent également un ensemble différent de fonctions.

Vous noterez si vous inspectez la console si vous exécutez vos scripts que l' tableélément DOM contient à la fois a childNodes NodeList[2]et a children HTMLCollection[1]. Pourquoi sont-ils différents? Comme HTMLCollectionne peut contenir que des nœuds d'élément, NodeList contient également un nœud de texte.

entrez la description de l'image ici

1. Quelle est la différence entre document.getElementsByTagName("td")et$("td") ?

document.getElementsByTagName("td")renvoie un tableau d'éléments DOM (a NodeList), $("td")est appelée un objet jQuery qui présente les éléments de document.getElementsByTagName("td")ses propriétés 0, 1,2 , etc. La principale différence est que l'objet jQuery est un peu plus lent à récupérer , mais donne accès à tous les à portée de main Fonctions jQuery.

2. $("#myTable")et $("td")sont des objets ( jQueryobjets). Pourquoi est-ceconsole.log affiche également le tableau des éléments DOM à côté d'eux, et ne sont-ils pas des objets et pas un tableau?

Ce sont des objets avec leurs propriétés 0, 1, 2, etc. ensemble aux éléments DOM. Voici un exemple simple: comment cela fonctionne:

jsFiddle

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

3. Qu'est-ce que les "NodeLists" insaisissables et comment en sélectionner une?

Vous les avez récupérés dans votre code getElementsByClassNameet les getElementsByTagNamedeux renvoient des NodeLists

NodeList

Daniel Imms
la source
Comment avez-vous affiché le DOM dans votre 3ème réponse? Merci!
user1032531
@ user1032531 qui sont les outils de développement Chrome. Au fait, j'ai mis à jour le début de la réponse.
Daniel Imms
Le journal de type tableau est principalement le résultat de la lengthpropriété, et non des noms de propriété numériques. Et qu'est-ce que votre exemple d'alerte d'une chaîne a à voir console.log?
Bergi
Cela montrait comment vous pouvez avoir des propriétés numériques sur des objets. J'essaie de mettre l'accent sur le fait que ce sont des objets, pas des tableaux.
Daniel Imms
9

Remarque additionnelle

Quelle est la différence entre une HTMLCollection et une NodeList?

Une HTMLCollection contient uniquement des nœuds d'élément ( balises ) et une NodeList contient tous les nœuds .

Il existe quatre types de nœuds:

  1. nœud d'élément
  2. nœud d'attribut
  3. noeud de texte
  4. noeud de commentaire

nodeTypes

Les espaces à l'intérieur des éléments sont considérés comme du texte et le texte est considéré comme des nœuds.

Considérer ce qui suit:

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

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

Pas d'espace blanc: <ul id="myList"><li>List item</li></ul>

Différence entre HTMLCollection et une NodeList

Soleil
la source
2

$("td")est un objet jQuery étendu et il a des méthodes jQuery, il retourne un objet jquery qui contient un tableau d'objets html. document.getElementsByTagName("td")est la méthode js brute et renvoie NodeList. Voir cet article

Karaxuna
la source
Merci Karaxuna. Oui, j'avais regardé cet article. Je ne sais pas si cela a aidé, mais m'a définitivement fait poser plus de questions :)
user1032531
Merci @karaxuna. Article utile, très bien expliqué.
Giuseppe
0

Les objets NodeList sont des collections de Node, renvoyées par exemple par x. propriété childNodes ou méthode document.querySelectorAll () . Dans certains cas, le NodeList est en direct , ce qui signifie que les changements dans les DOM automatiquement mis à jour la collection! Par exemple, Node.childNodes est en direct:

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.

Mais dans certains autres cas, la NodeList est statique , où toute modification dans le DOM n'affecte pas le contenu de la collection. querySelectorAll () renvoie une NodeList statique.

La HTMLCollection est une collection d'éléments vivants et ordonnés (elle est automatiquement mise à jour lorsque le document sous-jacent est modifié). Il peut être le résultat de propriétés comme en tant qu'enfants ou de méthodes comme document.getElementsByTagName () , et ne peut avoir que HTMLElement comme éléments.

HTMLCollection expose également ses membres directement en tant que propriétés par nom et index:

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

Le HTMLElement n'est qu'un type de nœuds:

Nœud << Héritage HTMLElement

Le nœud peut être de plusieurs types . Les plus importants sont les suivants:

  • element (1): un nœud d'élément tel que <p>ou <div>.
  • attribut (2): un attribut d'un élément. Les attributs d'élément n'implémentent plus l'interface Node dans la spécification DOM4!
  • text (3): Le texte réel de l'élément ou de l'attribut.
  • comment (8): un nœud de commentaire.
  • document (9): un nœud de document.

Donc, une grande différence est que HTMLCollection ne contient que HTMLElements mais NodeList contient également les commentaires, les textes d'espaces blancs (caractères de retour chariot, espaces ..), etc. Vérifiez-le comme dans l'extrait de code suivant:

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>

HTMLCollection et NodeList contiennent la propriété length que vous pouvez utiliser pour boucler sur leurs éléments. N'utilisez pas for ... in ou for each ... in pour énumérer les éléments dans NodeLists, car ils énuméreront également sa longueur et ses propriétés d'élément et provoqueront des erreurs si votre script suppose qu'il ne doit traiter que des objets élément. De plus, for..in n'est pas garanti de visiter les propriétés dans un ordre particulier.

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

Tant de choses ont déjà été dites, mais j'ai pensé qu'une version plus résumée de la réponse avec un exemple pour expliquer les différences entre HTMLCollectionet NodeListserait utile.

Types de nœuds dans DOM

  • Il existe 12 types de nœuds différents, qui peuvent avoir des enfants de différents types de nœuds:

entrez la description de l'image ici

  • Nous pouvons utiliser les trois propriétés suivantes pour inspecter et interroger les nœuds dans DOM:

    • nodeType Propriété
    • nodeName Propriété
    • nodeValue Propriété
  • le nodeType propriété renvoie le type de nœud, sous forme de nombre, du nœud spécifié.

    • Si le nœud est un nœud d'élément, la nodeTypepropriété retournera 1 .
    • Si le nœud est un nœud d'attribut, la nodeTypepropriété retournera 2 .
    • Si le nœud est un nœud de texte, la nodeTypepropriété retournera 3 .
    • Si le nœud est un nœud de commentaire, la nodeTypepropriété retournera 8 .
    • Cette propriété est en lecture seule.

HTMLCollection vs NodeList

entrez la description de l'image ici

Nous pouvons comprendre les différences entre HTMLCollectionetNodeList plus clairement avec l'exemple suivant. S'il vous plaît, essayez de vérifier les sorties dans votre propre console de navigateur pour avoir une meilleure compréhension.

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