Comportamiento extraño al iterar sobre HTMLCollection desde getElementsByClassName
Escribí una función para cambiar la clase de elementos para cambiar sus propiedades. Por alguna razón, sólo algunos de los elementos han cambiado. Me tomó algunas horas encontrar una solución, pero me parece extraño. Quizás puedas explicarme esto.
Esto no funciona:
function replace(){
var elements = document.getElementsByClassName('classOne');
for (var i = 0; i < elements.length; i++) {
elements[i].className = 'classTwo';
}
}
Consulte JSFiddle : solo uno de cada dos elementos se ve afectado; sólo uno de cada dos elementos rojos cambia de color a azul.
Así que cambié la expresión final del for
bucle para que no se incremente i
más:
function replace(){
var elements = document.getElementsByClassName('classOne');
for (var i = 0; i < elements.length; i) { // Here’s the difference
elements[i].className = 'classTwo';
}
}
¡Esto funciona bien! Parece que push
se llama y no se necesita ningún incremento. ¿Esto es normal? Es diferente de los ejemplos que he visto.
Lo que está pasando es un extraño efecto secundario. Cuando reasignas className
cada elemento de elements
, ¡el elemento se elimina de la matriz! (En realidad, como señala @user2428118, elements
es un objeto similar a una matriz , no una matriz. Consulte este hilo para conocer la diferencia). Esto se debe a que ya no tiene el classOne
nombre de clase. Cuando su ciclo salga (en el segundo caso), la elements
matriz estará vacía.
Podrías escribir tu bucle como:
while (elements.length) {
elements[0].className = 'classTwo'; // removes elements[0] from elements!
}
En el primer caso, al incrementar i
, estás omitiendo la mitad de los elementos (originales) que tienen class classOne
.
Excelente pregunta, por cierto. Bien investigado y claro.
getElementsByClassName
devuelve una lista de nodos. Una colección NodeList es una colección viva, lo que significa que la modificación del documento afecta a la colección. más