¿Qué devuelven los métodos querySelectorAll y getElementsBy*?
¿Funcionan getElementsByClassName
(y funciones similares como getElementsByTagName
y querySelectorAll
) igual getElementById
o devuelven una matriz de elementos?
La razón por la que pregunto es porque estoy intentando cambiar el estilo de todos los elementos usando getElementsByClassName
. Vea abajo.
//doesn't work
document.getElementsByClassName('myElement').style.size = '100px';
//works
document.getElementById('myIdElement').style.size = '100px';
Su getElementById
código funciona ya que los ID deben ser únicos y, por lo tanto, la función siempre devuelve exactamente un elemento (o null
si no se encontró ninguno).
Sin embargo, los métodos
getElementsByClassName
,
getElementsByName
,
getElementsByTagName
y
getElementsByTagNameNS
devuelven una colección iterable de elementos.
Los nombres de los métodos proporcionan una pista: getElement
implica singular , mientras que getElements
implica plural .
El método querySelector
también devuelve un único elemento y querySelectorAll
una colección iterable.
La colección iterable puede ser a NodeList
o HTMLCollection
.
getElementsByName
y querySelectorAll
ambos están especificados para devolver un NodeList
; los otros getElementsBy*
métodos están especificados para devolver un HTMLCollection
, pero tenga en cuenta que algunas versiones de navegador implementan esto de manera diferente.
Ambos tipos de colecciones no ofrecen las mismas propiedades que ofrecen los Elementos, Nodos o tipos similares; es por eso que la lectura style
de document.getElements
... (
... )
falla. En otras palabras: a NodeList
o an HTMLCollection
no tiene a style
; sólo un Element
tiene un style
.
Estas colecciones "similares a matrices" son listas que contienen cero o más elementos, sobre los cuales es necesario iterar para poder acceder a ellas. Si bien puedes iterar sobre ellos de manera similar a una matriz, ten en cuenta que son diferentes de Array
s .
En los navegadores modernos, puede convertir estos iterables en una matriz adecuada con Array.from
; entonces puedes usar forEach
otros métodos de matriz, por ejemplo, métodos de iteración :
Array.from(document.getElementsByClassName("myElement"))
.forEach((element) => element.style.size = "100px");
En navegadores antiguos que no admiten Array.from
los métodos de iteración, aún puedes usar Array.prototype.slice.call
. Luego puedes iterar sobre él como lo harías con una matriz real:
var elements = Array.prototype.slice
.call(document.getElementsByClassName("myElement"));
for(var i = 0; i < elements.length; ++i){
elements[i].style.size = "100px";
}
También puede iterar sobre NodeList
o HTMLCollection
mismo, pero tenga en cuenta que, en la mayoría de las circunstancias, estas colecciones están activas ( documentos MDN , especificaciones DOM ), es decir, se actualizan a medida que cambia el DOM. Entonces, si inserta o elimina elementos mientras realiza el bucle, asegúrese de no omitir accidentalmente algunos elementos ni crear un bucle infinito . La documentación de MDN siempre debe indicar si un método devuelve una colección activa o estática.
Por ejemplo, a NodeList
ofrece algunos métodos de iteración, como forEach
en los navegadores modernos:
document.querySelectorAll(".myElement")
.forEach((element) => element.style.size = "100px");
for
También se puede utilizar un bucle simple :
var elements = document.getElementsByClassName("myElement");
for(var i = 0; i < elements.length; ++i){
elements[i].style.size = "100px";
}
Aparte: .childNodes
produce un live NodeList
y .children
produce un live HTMLCollection
, por lo que estos dos captadores también deben manejarse con cuidado.
Hay algunas bibliotecas como jQuery que acortan un poco las consultas DOM y crean una capa de abstracción sobre "un elemento" y "una colección de elementos":
$(".myElement").css("size", "100px");
Estás usando una matriz como objeto, la diferencia entre getElementbyId
y
getElementsByClassName
es que:
getElementbyId
devolverá un objeto Elemento o nulo si no se encuentra ningún elemento con el IDgetElementsByClassName
devolverá una HTMLCollection activa , posiblemente de longitud 0 si no se encuentran elementos coincidentes
getElementsByClassName
El
getElementsByClassName(classNames)
método toma una cadena que contiene un conjunto desordenado de tokens únicos separados por espacios que representan clases. Cuando se llama, el método debe devolver unNodeList
objeto activo que contenga todos los elementos del documento que tengan todas las clases especificadas en ese argumento, habiendo obtenido las clases dividiendo una cadena en espacios. Si no se especifican tokens en el argumento, el método debe devolver una NodeList vacía.
https://www.w3.org/TR/2008/WD-html5-20080610/dom.html#getelementsbyclassname
obtenerElementoPorId
El método getElementById() accede al primer elemento con la identificación especificada.
https://developer.mozilla.org/en-US/docs/Web/API/Document/getElementById
en tu código las líneas:
1- document.getElementsByClassName('myElement').style.size = '100px';
NO funcionará como se esperaba, porque getElementByClassName
devolverá una matriz, y la matriz NO tendrá la style
propiedad, puede acceder a cada una element
iterando a través de ellas.
Es por eso que la función getElementById
funcionó para usted, esta función devolverá el objeto directo. Por lo tanto podrá acceder a la style
propiedad.
La siguiente descripción está tomada de esta página :
El método getElementsByClassName() devuelve una colección de todos los elementos del documento con el nombre de clase especificado, como un objeto NodeList.
El objeto NodeList representa una colección de nodos. Se puede acceder a los nodos mediante números de índice. El índice comienza en 0.
Consejo: puede usar la propiedad de longitud del objeto NodeList para determinar la cantidad de elementos con un nombre de clase específico, luego puede recorrer todos los elementos y extraer la información que desee.
Entonces, como parámetro getElementsByClassName
aceptaría un nombre de clase.
Si este es tu cuerpo HTML:
<div id="first" class="menuItem"></div>
<div id="second" class="menuItem"></div>
<div id="third" class="menuItem"></div>
<div id="footer"></div>
luego var menuItems = document.getElementsByClassName('menuItem')
devolvería una colección (no una matriz) de los 3 <div>
s superiores, ya que coinciden con el nombre de clase dado.
Luego puede iterar sobre esta <div>
colección de nodos (s en este caso) con:
for (var menuItemIndex = 0 ; menuItemIndex < menuItems.length ; menuItemIndex ++) {
var currentMenuItem = menuItems[menuItemIndex];
// do stuff with currentMenuItem as a node.
}
Consulte esta publicación para obtener más información sobre las diferencias entre elementos y nodos.
En otras palabras
document.querySelector()
selecciona solo el primer elemento del selector especificado. Entonces no muestra una matriz, es un valor único. Similar adocument.getElementById()
which recupera solo elementos de identificación, ya que las identificaciones deben ser únicas.document.querySelectorAll()
selecciona todos los elementos con el selector especificado y los devuelve en una matriz. Similar a solodocument.getElementsByClassName()
para clases ydocument.getElementsByTagName()
etiquetas.
¿Por qué utilizar querySelector?
Se utiliza únicamente con el único propósito de facilitar y brevedad.
¿Por qué utilizar getElement/sBy?*
Rendimiento más rápido.
¿A qué se debe esta diferencia de rendimiento?
Ambas formas de selección tienen el propósito de crear una NodeList para su uso posterior.
querySelectors genera una NodeList estática con los selectores, por lo que primero debe crearse desde cero.
getElement/sBy* adapta inmediatamente la NodeList activa existente del DOM actual.
Entonces, cuándo usar qué método depende de usted/su proyecto/su dispositivo.
Información
Demostración de todos los métodos Prueba de rendimiento
de la documentación de NodeList