javascript - style - JS: iterando sobre el resultado de getElementsByClassName usando Array.forEach
ocultar clase javascript (8)
¿El resultado de getElementsByClassName es una matriz?
No
Si no, ¿qué es?
Al igual que con todos los métodos DOM que devuelven varios elementos, es una lista de nodos, consulte https://developer.mozilla.org/en/DOM/document.getElementsByClassName
Quiero iterar sobre algunos elementos DOM, estoy haciendo esto:
document.getElementsByClassName( "myclass" ).forEach( function(element, index, array) {
//do stuff
});
pero obtengo un error: document.getElementsByClassName ("myclass"). forEach no es una función
Estoy usando Firefox 3, así que sé que ambos getElementsByClassName
y Array.forEach
están presentes. Esto funciona bien:
[2, 5, 9].forEach( function(element, index, array) {
//do stuff
});
¿El resultado de getElementsByClassName
una matriz? Si no, ¿qué es?
Como ya se dijo, getElementsByClassName
devuelve una HTMLCollection , que se define como
[Exposed=Window]
interface HTMLCollection {
readonly attribute unsigned long length;
getter Element? item(unsigned long index);
getter Element? namedItem(DOMString name);
};
Anteriormente, algunos navegadores devolvían una NodeList en NodeList lugar.
[Exposed=Window]
interface NodeList {
getter Node? item(unsigned long index);
readonly attribute unsigned long length;
iterable<Node>;
};
La diferencia es importante, porque DOM4 ahora define NodeList s como iterable.
Según el borrador de Web IDL ,
Los objetos que implementan una interfaz que se declara como iterable soportan ser iterados para obtener una secuencia de valores.
Nota : En el enlace de idioma de ECMAScript, una interfaz que es iterable tendrá "entradas", "para cada", "claves", "valores" y propiedades de @@iterator en su objeto de prototipo de interfaz .
Eso significa que, si desea usar forEach
, puede usar un método DOM que devuelve una lista de nodos , como querySelectorAll
.
document.querySelectorAll(".myclass").forEach(function(element, index, array) {
// do stuff
});
Tenga en cuenta que esto aún no es ampliamente compatible. Ver también para cada método de Node.childNodes?
Editar: aunque el tipo de devolución ha cambiado en las nuevas versiones de HTML (ver la respuesta actualizada de Tim Down), el siguiente código aún funciona.
Como otros han dicho, es una lista de nodos. Aquí hay un ejemplo completo y funcional que puedes probar:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<script>
function findTheOddOnes()
{
var theOddOnes = document.getElementsByClassName("odd");
for(var i=0; i<theOddOnes.length; i++)
{
alert(theOddOnes[i].innerHTML);
}
}
</script>
</head>
<body>
<h1>getElementsByClassName Test</h1>
<p class="odd">This is an odd para.</p>
<p>This is an even para.</p>
<p class="odd">This one is also odd.</p>
<p>This one is not odd.</p>
<form>
<input type="button" value="Find the odd ones..." onclick="findTheOddOnes()">
</form>
</body>
</html>
Esto funciona en IE 9, FF 5, Safari 5 y Chrome 12 en Win 7.
El resultado de getElementsByClassName()
no es una matriz, sino un objeto similar a una matriz . Específicamente se llama una HTMLCollection
, que no debe confundirse con NodeList
( que tiene su propio método para cada uno ).
Una manera simple con ES2015 para convertir un objeto similar a una matriz para usar con Array.prototype.forEach()
que aún no se ha mencionado es usar el operador spread o la sintaxis extendida :
const elementsArray = document.getElementsByClassName(''myclass'');
[...elementsArray].forEach((element, index, array) => {
// do something
});
No devuelve una Array
, devuelve una lista de NodeList .
No. Como se especifica en DOM4 , es una HTMLCollection
(en los navegadores modernos, al menos. Los navegadores antiguos devolvieron una NodeList
).
En todos los navegadores modernos (casi cualquier otro IE <= 8), puede llamar al método forEach
, pasándole la lista de elementos (ya sea HTMLCollection
o NodeList
) como this
valor:
var els = document.getElementsByClassName("myclass");
Array.prototype.forEach.call(els, function(el) {
// Do stuff here
console.log(el.tagName);
});
// Or
[].forEach.call(els, function (el) {...});
Puede usar Array.from
para convertir collection en array, que es mucho más limpio que Array.prototype.forEach.call
:
Array.from(document.getElementsByClassName("myclass")).forEach(
function(element, index, array) {
// do stuff
}
);
En los navegadores más antiguos que no son compatibles con Array.from
, debe usar algo como Babel.
ES6 también agrega esta sintaxis:
[...document.getElementsByClassName("myclass")].forEach(
(element, index, array) => {
// do stuff
}
);
Descansar la desestructuración con ...
funciona en todos los objetos similares a una matriz, no solo en las matrices, entonces se usa una buena sintaxis de matriz para construir una matriz a partir de los valores.
Si bien la función alternativa querySelectorAll
(que hace que getElementsByClassName
sea obsoleta) devuelve una colección que sí tiene forEach
forma nativa, forEach
otros métodos como map
o filter
, por lo que esta sintaxis sigue siendo útil:
[...document.querySelectorAll(".myclass")].map(
(element, index, array) => {
// do stuff
}
);
[...document.querySelectorAll(".myclass")].map(element => element.innerHTML);
O puede usar querySelectorAll
que devuelve NodeList :
document.querySelectorAll(''.myclass'').forEach(...)
Compatible con navegadores modernos (incluido Edge, pero no IE):
¿Puedo usar querySelectorAll
NodeList.prototype.forEach()