queryselectorall parse collection array javascript dom

javascript - parse - Para bucle para elementos HTMLCollection



queryselectorall (10)

Estoy tratando de establecer el ID de todos los elementos en una colección HTMLC. Escribí el siguiente código:

var list= document.getElementsByClassName("events"); console.log(list[0].id); //first console output for (key in list){ console.log(key.id); //second console output }

Pero tengo la salida de follwo en la consola:

event1 undefined

que no es lo que esperaba. ¿Por qué la second console output undefined pero la first console output es event1 ?


A partir de marzo de 2016, en Chrome 49.0, for...of trabajos para HTMLCollection :

this.headers = this.getElementsByTagName("header"); for (var header of this.headers) { console.log(header); }

Vea aquí la documentación .

Pero solo funciona si aplica la siguiente solución alternativa antes de usar el for...of :

HTMLCollection.prototype[Symbol.iterator] = Array.prototype[Symbol.iterator];

Lo mismo es necesario para usar for...of con NodeList :

NamedNodeMap.prototype[Symbol.iterator] = Array.prototype[Symbol.iterator];

Creo / espero for...of pronto funcionará sin la solución anterior. El tema abierto está aquí:

https://bugs.chromium.org/p/chromium/issues/detail?id=401699

Actualización: vea el comentario de Expenzor a continuación: Este problema se solucionó a partir de abril de 2016. No es necesario agregar HTMLCollection.prototype [Symbol.iterator] = Array.prototype [Symbol.iterator]; iterar sobre una colección HTM con for ... of


Eeek No debe iterar sobre una lista de nodeList o HTMLCollection con for/in y cuando lo haga, debe recuperar el valor de la lista, usando el índice en su iteración.

En ES5 (y compatible con cualquier cosa posterior), puedes iterar así:

var list= document.getElementsByClassName("events"); for (var i = 0; i < list.length; i++) { console.log(list[i].id); //second console output }

for/in está pensado para iterar las propiedades de un objeto. No está pensado para iterar una matriz o un objeto similar a una matriz que es una colección HTMLC. Solo probé esto en Chrome e iterándolo de la forma en que lo estabas iterando recuperará los elementos de la lista (índices 0, 1, 2, etc.), pero también recuperará la length y las propiedades del item . La iteración for/in simplemente no funcionará para una HTMLCollection.

Consulte http://jsfiddle.net/jfriend00/FzZ2H/ para http://jsfiddle.net/jfriend00/FzZ2H/ por qué no puede iterar una colección HTM con for/in .

En Firefox, tu for/in iteration devolvería estos elementos (todas las propiedades iterables del objeto):

0 1 2 item namedItem @@iterator length

Con suerte, ahora puede ver por qué quiere usar for (var i = 0; i < list.length; i++) lugar, así que solo obtiene 0 , 1 y 2 en su iteración.

Actualización para ES6 en 2015

Agregado a ES6 está Array.from() que convertirá una estructura similar a una matriz en una matriz real. Eso permite enumerar una lista directamente como esta:

"use strict"; Array.from(document.getElementsByClassName("events")).forEach(function(item) { console.log(item.id); });

Demostración de trabajo (en Firefox, Chrome y Edge a partir de abril de 2016): https://jsfiddle.net/jfriend00/8ar4xn2s/

Actualización para ES6 en 2016

Ahora puede usar el ES6 para / de construcción con un NodeList y una HTMLCollection simplemente agregando esto a su código:

NodeList.prototype[Symbol.iterator] = Array.prototype[Symbol.iterator]; HTMLCollection.prototype[Symbol.iterator] = Array.prototype[Symbol.iterator];

Entonces, puedes hacer:

var list = document.getElementsByClassName("events"); for (var item of list) { log(item.id); }

Esto funciona en la versión actual de Chrome, Firefox y Edge.

Demostración de trabajo: http://jsfiddle.net/jfriend00/joy06u4e/ .

Segunda actualización para ES6 en diciembre de 2016

A partir de diciembre de 2016, el soporte de Symbol.iterator se ha incorporado en Chrome v54 y Firefox v50, por lo que el siguiente código funciona por sí solo. Todavía no está incorporado para Edge.

var list = document.getElementsByClassName("events"); for (let item of list) { log(item.id); }

Demostración de trabajo (en Chrome y Firefox): http://jsfiddle.net/jfriend00/3ddpz8sp/

Tercera actualización para ES6 en diciembre de 2017

A partir de diciembre de 2017, esta capacidad funciona en Edge 41.16299.15.0 para una lista de nodeList como en document.querySelectorAll() , pero no en HTMLCollection como en document.getElementsByClassName() por lo que debe asignar manualmente el iterador para usarlo en Edge Una HTMLCollection . Es un misterio total por qué arreglarían un tipo de colección, pero no el otro. Pero, al menos puede usar el resultado de document.querySelectorAll() con ES6 for/of sintaxis en las versiones actuales de Edge ahora.

También he actualizado el jsFiddle anterior para que compruebe tanto HTMLCollection como nodeList separado y capture la salida en el jsFiddle mismo.

Cuarta actualización para ES6 en marzo de 2018

Por mesqueeeb, el soporte de Symbol.iterator se ha incorporado a Safari, por lo que puede usar for (let item of list) para document.getElementsByClassName() o document.querySelectorAll() .

Quinta actualización para ES6 en abril de 2018

Aparentemente, el soporte para iterar una HTMLCollection con for/of vendrá a Edge 18 en otoño de 2018.

Sexta actualización para ES6 en noviembre de 2018

Puedo confirmar que con Microsoft Edge v18 incluido en la actualización de Windows de otoño de 2018, ahora puede iterar tanto una HTMLCollection como una NodeList para / of en Edge.


En ES6, podrías hacer algo como [...collection] , o Array.from(collection) ,

let someCollection = document.querySelectorAll(someSelector) [...someCollection].forEach(someFn) //or Array.from(collection).forEach(someFn)


La alternativa a Array.from es usar Array.prototype.forEach.call

forEach: Array.prototype.forEach.call(htmlCollection, i => { console.log(i) });

mapa: Array.prototype.map.call(htmlCollection, i => { console.log(i) });

ect ...


Nervioso

if(!NodeList.prototype.forEach) { NodeList.prototype.forEach = function(fn, scope) { for(var i = 0, len = this.length; i < len; ++i) { fn.call(scope, this[i], i, this); } } }


No hay ninguna razón para usar las funciones de es6 para escapar for bucle si estás en IE9 o superior.

En ES5, hay dos buenas opciones. Primero, puede "pedir prestado" el Array para cada forEach como evan menciones .

Pero aún mejor ...

Use Object.keys() , que tiene forEach

Object.keys es esencialmente equivalente a hacer un for... in con un HasOwnProperty , pero es más suave.

var eventNodes = document.getElementsByClassName("events"); Object.keys(eventNodes).forEach(function (key) { console.log(eventNodes[key].id); });


No puede usar for / in en NodeList o HTMLCollection s. Sin embargo, puede usar algunos métodos de Array.prototype , siempre que los .call() y pase la NodeList o HTMLCollection como this .

Así que considere lo siguiente como una alternativa a jfriend00''s for loop :

var list= document.getElementsByClassName("events"); [].forEach.call(list, function(el) { console.log(el.id); });

Hay un buen artículo sobre MDN que cubre esta técnica. Tenga en cuenta su advertencia sobre la compatibilidad del navegador sin embargo:

[...] pasar un objeto host (como un NodeList ) a un método nativo (como forEach ) no se garantiza que funcione en todos los navegadores y se sabe que falla en algunos.

Entonces, si bien este enfoque es conveniente, un bucle for puede ser la solución más compatible con el navegador.

Actualización (30 de agosto de 2014): ¡ Eventualmente podrás usar ES6 for / of !

var list = document.getElementsByClassName("events"); for (el of list) console.log(el.id);

Ya es compatible con las versiones recientes de Chrome y Firefox.


Puedes agregar estas dos líneas:

HTMLCollection.prototype.forEach = Array.prototype.forEach; NodeList.prototype.forEach = Array.prototype.forEach;

HTMLCollection es devuelto por getElementsByClassName y getElementsByTagName

NodeList es devuelto por querySelectorAll

Así puedes hacer un forEach:

var selections = document.getElementsByClassName(''myClass''); /* alternative : var selections = document.querySelectorAll(''.myClass''); */ selections.forEach(function(element, i){ //do your stuffs });


Quieres cambiarlo a

var list= document.getElementsByClassName("events"); console.log(list[0].id); //first console output for (key in list){ console.log(list[key].id); //second console output }


Tuve un problema al usar forEach en IE 11 y también en Firefox 49

He encontrado una solución como esta

Array.prototype.slice.call(document.getElementsByClassName("events")).forEach(function (key) { console.log(key.id); }