Estaba trabajando en un breve script para cambiar <abbr>
el texto interno de los elementos, pero descubrí que nodelist
no tiene un forEach
método. Sé que nodelist
no se hereda de Array
, pero ¿no parece forEach
que sería un método útil tener? ¿Hay un problema de implementación en particular no soy consciente de que impide que se agregue forEach
a nodelist
?
Nota: Soy consciente de que Dojo y jQuery tienen forEach
de 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
forEach
y 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,
concat
tratará 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
x
era 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 quex
no era una matriz real.Durante algún tiempo hubo una propuesta para una
Elements
clase 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 browsers
parece 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.call
se puede acortar a[].forEach.call
Array.prototype.forEach.call
, es crear una matriz vacía y usar suforEach
mé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 true
fuente
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
NodeList
objeto ha implementado unforEach
mé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
forEach
mé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