Estaba trabajando en un breve script para cambiar <abbr>el texto interno de los elementos, pero descubrí que nodelistno tiene un forEachmétodo. Sé que nodelistno se hereda de Array, pero ¿no parece forEachque sería un método útil tener? ¿Hay un problema de implementación en particular no soy consciente de que impide que se agregue forEacha nodelist?
Nota: Soy consciente de que Dojo y jQuery tienen forEachde alguna forma sus nodelists. No puedo usar ninguno de los dos por limitaciones.
javascript
arrays
dom
foreach
Serpientes y Café
fuente
fuente

Respuestas:
NodeList ahora tiene forEach () en todos los navegadores principales
Consulte nodeList forEach () en MDN .
Respuesta original
Ninguna de estas respuestas explica por qué NodeList no hereda de Array, lo que le permite tener
forEachy todo lo demás.La respuesta se encuentra en este hilo es-discusion . En resumen, rompe la web:
Es decir, algún código hizo algo como
if (x instanceof Array) { otherArray.concat(x); } else { doSomethingElseWith(x); }Sin embargo,
concattratará las matrices "reales" (no la instancia de Array) de manera diferente a otros objetos:[1, 2, 3].concat([4, 5, 6]) // [1, 2, 3, 4, 5, 6] [1, 2, 3].concat(4) // [1, 2, 3, 4]lo que significa que el código anterior se rompió cuando
xera una NodeList, porque antes iba por eldoSomethingElseWith(x)camino, mientras que después seguía por elotherArray.concat(x)camino, lo que hizo algo extraño ya quexno era una matriz real.Durante algún tiempo hubo una propuesta para una
Elementsclase que era una subclase real de Array, y se usaría como "la nueva NodeList". Sin embargo, eso se eliminó del estándar DOM , al menos por ahora, ya que aún no era factible de implementar por una variedad de razones técnicas y relacionadas con las especificaciones.fuente
NodeList now has forEach() in all major browsersparece implicar que IE no es un navegador importante. Con suerte, eso es cierto para algunas personas, pero no es cierto para mí (todavía).Tu puedes hacer
Array.prototype.forEach.call (nodeList, function (node) { // Your code here. } );fuente
Array.prototype.forEach.callse puede acortar a[].forEach.callArray.prototype.forEach.call, es crear una matriz vacía y usar suforEachmétodo.Puede considerar crear una nueva matriz de nodos.
var nodeList = document.getElementsByTagName('div'), nodes = Array.prototype.slice.call(nodeList,0); // nodes is an array now. nodes.forEach(function(node){ // do your stuff here. });Nota: Esta es solo una lista / matriz de referencias de nodos que estamos creando aquí, no hay nodos duplicados.
nodes[0] === nodeList[0] // will be truefuente
Array.prototype.forEach.call(nodeList, fun).var forEach = Array.prototype.forEach.call(nodeList, callback);. Ahora puede simplemente llamarforEach(nodeList, callback);Nunca digas nunca, es 2016 y el
NodeListobjeto ha implementado unforEachmétodo en la última versión de Chrome (v52.0.2743.116).Es demasiado pronto para usarlo en producción, ya que otros navegadores aún no lo admiten (FF 49 probado), pero supongo que pronto se estandarizará.
fuente
Array.prototype.slice.call(nodelist).forEach(…)que es estándar y funciona en navegadores antiguos.En resumen, es un conflicto de diseño implementar ese método.
De MDN:
Fuente: https://developer.mozilla.org/en-US/docs/DOM/NodeList (desplácese hacia abajo hasta ¿Por qué no puedo usar forEach o mapa en una NodeList? )
fuente
myNodeList --> NodeList.prototype --> Array.prototype --> Object.prototype --> null?Si desea usar forEach en NodeList, simplemente copie esa función de Array:
NodeList.prototype.forEach = Array.prototype.forEach;Eso es todo, ahora puede usarlo de la misma manera que lo haría para Array:
document.querySelectorAll('td').forEach(function(o){ o.innerHTML = 'text'; });fuente
En ES2015, ahora puede usar el
forEachmétodo para la lista de nodos.document.querySelectorAll('abbr').forEach( el => console.log(el));Ver el enlace MDN
Sin embargo, si desea usar colecciones HTML u otros objetos tipo matriz, en es2015, puede usar el
Array.from()método. Este método toma un objeto iterable o similar a una matriz (incluidas nodeList, colecciones HTML, cadenas, etc.) y devuelve una nueva instancia de matriz. Puedes usarlo así:const elements = document.getElementsByTagName('abbr'); Array.from(elements).forEach( el => console.log(el));Como el
Array.from()método es intercambiable, puede usarlo en un código es5 como estevar elements = document.getElementsByTagName('abbr'); Array.from(elements).forEach( function(el) { console.log(el); });Para obtener más información, consulte la página MDN .
Para comprobar la compatibilidad del navegador actual .
O
otra forma de es2015 es utilizar el operador de propagación.
[...document.querySelectorAll('abbr')].forEach( el => console.log(el));Operador de propagación MDN
Operador de propagación: compatibilidad con el navegador
fuente
Mi solución:
//foreach for nodeList NodeList.prototype.forEach = Array.prototype.forEach; //foreach for HTML collection(getElementsByClassName etc.) HTMLCollection.prototype.forEach = Array.prototype.forEach;fuente
NodeList es parte de DOM API. Mire los enlaces de ECMAScript que también se aplican a JavaScript. http://www.w3.org/TR/DOM-Level-2-Core/ecma-script-binding.html . NodeList y una propiedad de longitud de solo lectura y una función de elemento (índice) para devolver un nodo.
La respuesta es, tienes que iterar. No hay alternativa. Foreach no funcionará. Trabajo con enlaces de API DOM de Java y tengo el mismo problema.
fuente
NodeList.forEach(function(item, index, nodeList) { // code block here });En IE, use la respuesta de akuhn :
[].forEach.call(NodeList, function(item, index, array) { // code block here });fuente