Diferencia entre HTMLCollection, NodeLists y matrices de objetos

94

Siempre he estado confundido entre HTMLCollections, objetos y matrices cuando se trata de DOM. Por ejemplo...

  1. ¿Cuál es la diferencia entre document.getElementsByTagName("td")y $("td")?
  2. $("#myTable")y $("td")son objetos (objetos jQuery). ¿Por qué console.log también muestra la matriz de elementos DOM a su lado, y no son objetos y no una matriz?
  3. ¿De qué se tratan las esquivas "NodeLists" y cómo selecciono una?

Proporcione también cualquier interpretación del siguiente guión.

Gracias

[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>
usuario1032531
fuente
Creo que podría agregar lo siguiente para la posteridad. (a) En JavaScript moderno, una mejor comparación sería entre document.querySelectorAll('td')y $('td'). (b) La diferencia fundamental es que jQuery trabaja con su propio tipo de objeto que contiene, entre otras cosas, una colección numerada de elementos HTML; esta colección no es ninguna de las anteriores, y el objeto jQuery es esencialmente una envoltura de los verdaderos elementos DOM.
Manngo

Respuestas:

113

Primero explicaré la diferencia entre NodeListy HTMLCollection.

Ambas interfaces son colecciones de nodos DOM. Se diferencian en los métodos que proporcionan y en el tipo de nodos que pueden contener. Mientras que a NodeListpuede contener cualquier tipo de nodo, HTMLCollectionse supone que an solo contiene nodos Element.
An HTMLCollectionproporciona los mismos métodos que ay, NodeListademás, un método llamado namedItem.

Las colecciones se utilizan siempre cuando se debe proporcionar acceso a varios nodos, por ejemplo, la mayoría de los métodos de selección (como getElementsByTagName) devuelven varios nodos o obtienen una referencia a todos los hijos ( element.childNodes).

Para obtener más información, consulte la especificación DOM4 - Colecciones .

¿Cuál es la diferencia entre document.getElementsByTagName("td")y $("td")?

getElementsByTagNamees el método de la interfaz DOM. Acepta un nombre de etiqueta como entrada y devuelve un HTMLCollection(consulte la especificación DOM4 ).

$("td")es presumiblemente jQuery. Acepta cualquier selector CSS / jQuery válido y devuelve un objeto jQuery.

Las mayores diferencias entre las colecciones DOM estándar y las selecciones de jQuery es que las colecciones DOM son típicamente activas (aunque no todos los métodos devuelven una colección en vivo), es decir, cualquier cambio en el DOM se refleja en las colecciones si se ven afectados. Son como una vista del árbol DOM, mientras que las selecciones de jQuery son instantáneas del árbol DOM en el momento en que se llamó a la función.

¿Por qué console.log también muestra la matriz de elementos DOM a su lado, y no son objetos y no una matriz?

Los objetos jQuery son objetos en forma de matriz , es decir, tienen propiedades numéricas y unlength propiedad (tenga en cuenta que las matrices son solo objetos en sí mismas). Los navegadores tienden a mostrar matrices y objetos similares a matrices de una manera especial, como [ ... , ... , ... ].

¿De qué se tratan las esquivas "NodeLists" y cómo selecciono una?

Vea la primera parte de mi respuesta. No puede seleccionar NodeList s, son los resultado de una selección.

Hasta donde yo sé, ni siquiera hay una manera de crear NodeLists programáticamente (es decir, crear uno vacío y agregar nodos más adelante), solo son devueltos por algunos métodos / propiedades DOM.

Felix Kling
fuente
2
@ user1032531: Bueno, si realiza algún cambio en uno de los elementos DOM seleccionados (por ejemplo, agregando un niño), entonces, por supuesto, verá el cambio ya que es el mismo elemento DOM. Pero, asumiendo que seleccionó todos los tdelementos, agregar un nuevo tdelemento más adelante no actualizará la selección automáticamente para contener el nuevo elemento.
Felix Kling
2
@FelixKling: Deberías mencionar que no todos NodeListlos correos electrónicos están en vivo.
Bergi
2
Ojalá fueran todos arreglos
SuperUberDuper
7
También parece que los métodos "claves", "entradas" y "forEach" los presento en NodeList, pero faltan en HTMLCollection
Krzysztof Grzybek
2
@KrzysztofGrzybek Eso es correcto y es súper molesto. ¿Por qué diablos uno tiene .forEach()y el otro no?
Robo Robok
30

0. ¿Cuál es la diferencia entre an HTMLCollectiony a NodeList?

Aquí tienes algunas definiciones.

Especificación DOM Nivel 1 - Definiciones de objetos varios :

Interfaz HTMLCollection

Una colección HTMLCollection es una lista de nodos. Se puede acceder a un nodo individual mediante el índice ordinal o el nombre del nodo o los atributos de identificación. Nota: Se asume que las colecciones en HTML DOM están activas, lo que significa que se actualizan automáticamente cuando se cambia el documento subyacente.

Especificación DOM Nivel 3 - NodeList

Interfaz NodeList

La interfaz NodeList proporciona la abstracción de una colección ordenada de nodos, sin definir ni restringir cómo se implementa esta colección. Los objetos NodeList del DOM están activos.

Se puede acceder a los elementos de NodeList mediante un índice integral, comenzando desde 0.

Por lo tanto, ambos pueden contener datos en vivo, lo que significa que el DOM se actualizará cuando lo hagan sus valores. También contienen un conjunto diferente de funciones.

Observará si inspecciona la consola si ejecuta sus scripts que el tableelemento DOM contiene tanto a childNodes NodeList[2]como a children HTMLCollection[1]. ¿Por qué son diferentes? Debido a HTMLCollectionque solo puede contener nodos de elementos, NodeList también contiene un nodo de texto.

ingrese la descripción de la imagen aquí

1. ¿Cuál es la diferencia entre document.getElementsByTagName("td")y $("td")?

document.getElementsByTagName("td")Devuelve una matriz de elementos DOM (a NodeList), $("td")que se llama un objeto jQuery que tiene los elementos de las document.getElementsByTagName("td")de sus propiedades 0, 1, 2, etc. La diferencia principal es que el objeto jQuery es un poco más lento para recuperar, pero da acceso a toda la mano Funciones de jQuery.

2. $("#myTable")y $("td")son objetos ( jQueryobjetos). ¿Por qué console.logtambién se muestra la matriz de elementos DOM junto a ellos, y no son objetos y no una matriz?

Son objetos con sus propiedades 0, 1, 2, etc conjunto de los elementos DOM. Aquí hay un ejemplo simple: de cómo funciona:

jsFiddle

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

3. ¿De qué se tratan las escurridizas "NodeLists" y cómo selecciono una?

Los ha estado recuperando en su código, getElementsByClassNamey getElementsByTagNameambos devuelven NodeLists

NodeList

Daniel Imms
fuente
¿Cómo mostraste el DOM en tu tercera respuesta? ¡Gracias!
user1032531
@ user1032531 que son las herramientas de desarrollo de Chrome. Por cierto, actualicé el inicio de la respuesta.
Daniel Imms
El registro similar a una matriz es principalmente el resultado de la lengthpropiedad, no de los nombres de propiedad numéricos. ¿Y con qué tiene que ver tu ejemplo de alertar a una cadena console.log?
Bergi
Eso estaba mostrando cómo se pueden tener propiedades numéricas en los objetos. Estoy tratando de enfatizar los hechos de que son objetos, no matrices.
Daniel Imms
9

Nota adicional

¿Cuál es la diferencia entre una HTMLCollection y una NodeList?

Una HTMLCollection contiene solo nodos de elementos ( etiquetas ) y una NodeList contiene todos los nodos .

Hay cuatro tipos de nodos:

  1. nodo de elemento
  2. nodo de atributo
  3. nodo de texto
  4. nodo de comentario

nodeTypes

Los espacios en blanco dentro de los elementos se consideran texto y el texto se considera nodos.

Considera lo siguiente:

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

Espacio en blanco: <ul id="myList"> <li>List item</li></ul>

Sin espacios en blanco: <ul id="myList"><li>List item</li></ul>

Diferencia entre HTMLCollection y NodeList

Dom
fuente
2

$("td")es un objeto jQuery extendido y tiene métodos jQuery, devuelve un objeto jquery que contiene una matriz de objetos html. document.getElementsByTagName("td")es el método js sin formato y devuelve NodeList. Ver este articulo

Karaxuna
fuente
Gracias Karaxuna. Sí, había mirado ese artículo. No sé si ayudó, pero definitivamente me hizo hacer más preguntas :)
user1032531
Gracias @karaxuna. Artículo útil, muy bien explicado.
Giuseppe
0

Los objetos NodeList son colecciones de Node, devueltos, por ejemplo, por x. propiedad childNodes o método document.querySelectorAll () . En algunos casos, el NodeList es en vivo , lo que significa que los cambios en el DOM se actualizan automáticamente la colección! Por ejemplo, Node.childNodes está activo:

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.

Pero en algunos otros casos, NodeList es estático , donde cualquier cambio en el DOM no afecta el contenido de la colección. querySelectorAll () devuelve una NodeList estática.

La HTMLCollection es una colección de elementos en vivo y ordenada (se actualiza automáticamente cuando se cambia el documento subyacente). Puede ser el resultado de propiedades como hijos o métodos como document.getElementsByTagName () , y solo podría tener HTMLElement como elementos.

HTMLCollection también expone sus miembros directamente como propiedades tanto por nombre como por índice:

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

El HTMLElement es solo un tipo de nodos:

Nodo << HTMLElement herencia

El nodo puede ser de varios tipos . Los más importantes son los siguientes:

  • elemento (1): un nodo de elemento como <p>o <div>.
  • atributo (2): un atributo de un elemento. ¡Los atributos del elemento ya no implementan la interfaz de nodo en la especificación DOM4!
  • text (3): el texto real del elemento o atributo.
  • comentario (8): un nodo de comentario.
  • document (9): un nodo de documento.

Entonces, una gran diferencia es que HTMLCollection contiene solo HTMLElements pero NodeList también contiene los comentarios, textos de espacios en blanco (caracteres de retorno de carro, espacios ...), etc. Compruébelo como en el siguiente fragmento:

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>

Tanto HTMLCollection como NodeList contienen la propiedad length que puede usar para recorrer sus elementos. No use for ... in o for each ... in para enumerar los elementos en NodeLists, ya que también enumerarán su longitud y propiedades del elemento y causarán errores si su secuencia de comandos asume que solo tiene que tratar con objetos de elemento. Además, no se garantiza que for..in visite las propiedades en ningún orden en particular.

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

Ya se ha dicho mucho, pero se pensó que una versión más resumida de la respuesta con un ejemplo para explicar las diferencias entre HTMLCollectiony NodeListayudaría.

Tipos de nodos en DOM

  • Hay 12 tipos de nodos diferentes, que pueden tener hijos de varios tipos de nodos:

ingrese la descripción de la imagen aquí

  • Podemos usar las siguientes tres propiedades para inspeccionar y consultar sobre los nodos en DOM:

    • nodeType Propiedad
    • nodeName Propiedad
    • nodeValue Propiedad
  • La nodeTypepropiedad devuelve el tipo de nodo, como un número, del nodo especificado.

    • Si el nodo es un nodo de elemento, la nodeTypepropiedad devolverá 1 .
    • Si el nodo es un nodo de atributo, la nodeTypepropiedad devolverá 2 .
    • Si el nodo es un nodo de texto, la nodeTypepropiedad devolverá 3 .
    • Si el nodo es un nodo de comentario, la nodeTypepropiedad devolverá 8 .
    • Esta propiedad es de sólo lectura.

HTMLCollection frente a NodeList

ingrese la descripción de la imagen aquí

Podemos entender las diferencias entre HTMLCollectiony NodeListmás claramente con el siguiente ejemplo. Por favor, intente verificar los resultados en la consola de su propio navegador para comprender mejor.

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