Je travaillais sur un court script pour changer le texte intérieur des éléments <abbr>
, mais j'ai constaté que nodelist
n'a pas de méthode forEach
. Je sais que nodelist
n'hérite pas de Array
, mais ne semble-t-il pas que forEach
serait une méthode utile? Existe-t-il un problème d'implémentation dont je ne suis pas au courant qui empêche d'ajouter forEach
à nodelist
?
Remarque: Je suis conscient que Dojo et jQuery ont tous les deux forEach
sous une forme quelconque pour leurs listes de nœuds. Je ne peux pas utiliser non plus en raison de limitations.
Voir nodeList forEach () on MDN .
Aucune de ces réponses n'explique pourquoi NodeList [] n'hérite pas de Array, lui permettant ainsi d'avoir forEach
et tout le reste.
La réponse est trouvée sur ce fil d'es-discussion . En bref, ça casse le web:
Le problème était un code qui supposait à tort que instanceof signifiait que l'instance était un tableau associé à Array.prototype.concat.
Il y avait un bogue dans la bibliothèque de fermeture de Google qui causait l'échec de presque toutes les applications de Google pour cette raison. La bibliothèque a été mise à jour dès que cela a été trouvé, mais il se peut qu'il y ait encore du code faisant la même hypothèse incorrecte en combinaison avec concat.
C'est-à-dire qu'un code a fait quelque chose comme
if (x instanceof Array) {
otherArray.concat(x);
} else {
doSomethingElseWith(x);
}
Cependant, concat
traitera les "vrais" tableaux (et non l'instance de Array) différemment des autres objets:
[1, 2, 3].concat([4, 5, 6]) // [1, 2, 3, 4, 5, 6]
[1, 2, 3].concat(4) // [1, 2, 3, 4]
cela signifie donc que le code ci-dessus a éclaté lorsque x
était une liste de noeuds, car avant de suivre le chemin doSomethingElseWith(x)
, puis de suivre le chemin otherArray.concat(x)
, ce qui avait un effet étrange puisque x
n'était pas un véritable tableau.
Pendant un certain temps, il a été proposé de créer une classe Elements
qui serait une véritable sous-classe de Array et qui serait utilisée comme "nouvelle liste de noeuds". Cependant, cela était retiré de la norme DOM , du moins pour le moment, car sa mise en œuvre n’était pas encore réalisable pour diverses raisons techniques et liées aux spécifications.
Tu peux faire
Array.prototype.forEach.call (nodeList, function (node) {
// Your code here.
} );
Vous pouvez envisager de créer un nouveau tableau de nœuds.
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.
});
Remarque: Ceci est juste une liste/tableau de références de nœuds que nous créons ici, pas de nœuds en double.
nodes[0] === nodeList[0] // will be true
Ne dites jamais jamais, c'est 2016 et l'objet NodeList
a implémenté une méthode forEach
dans le dernier chrome (v52.0.2743.116).
Il est trop tôt pour l'utiliser en production car les autres navigateurs ne le supportent pas encore (testé 49 FF), mais je suppose que cela sera bientôt normalisé.
En bref, c'est un conflit de conception pour mettre en œuvre cette méthode.
De MDN:
Pourquoi ne puis-je pas utiliser forEach ou mapper sur une liste de noeuds?
NodeList s'utilise beaucoup comme des tableaux et il serait tentant de utilisez les méthodes Array.prototype sur eux. Ceci est cependant impossible.
JavaScript a un mécanisme d'héritage basé sur des prototypes. Tableau les instances héritent des méthodes de tableau (telles que forEach ou map) car leurs La chaîne prototype ressemble à ce qui suit:
myArray --> Array.prototype --> Object.prototype --> null
(la chaîne de prototypes d'un objet peut être obtenue en appelant plusieurs fois Object.getPrototypeOf)forEach, map et les likes sont des propriétés propres à Array.prototype objet.
Contrairement aux tableaux, la chaîne de prototypes NodeList se présente comme suit:
myNodeList --> NodeList.prototype --> Object.prototype --> null
NodeList.prototype contient la méthode de l'élément, mais aucun des fichiers Méthodes Array.prototype, elles ne peuvent donc pas être utilisées sur NodeLists.
Source: https://developer.mozilla.org/en-US/docs/DOM/NodeList (descendez jusqu'à Pourquoi ne puis-je pas utiliser forEach ou mapper sur une NodeList?)
Si vous souhaitez utiliser forEach sur NodeList, copiez simplement cette fonction à partir de Array:
NodeList.prototype.forEach = Array.prototype.forEach;
C'est tout, vous pouvez maintenant l'utiliser de la même manière que vous le feriez pour Array:
document.querySelectorAll('td').forEach(function(o){
o.innerHTML = 'text';
});
Dans ES2015, vous pouvez maintenant utiliser la méthode forEach
pour la liste de noeuds.
document.querySelectorAll('abbr').forEach( el => console.log(el));
Voir le MDN Link
Toutefois, si vous souhaitez utiliser des collections HTML ou d'autres objets de type tableau, vous pouvez utiliser la méthode Array.from()
dans es2015. Cette méthode prend un objet semblable à un tableau ou itératif (y compris nodeList, Collections HTML, chaînes, etc.) et renvoie une nouvelle instance Array. Vous pouvez l'utiliser comme ceci:
const elements = document.getElementsByTagName('abbr');
Array.from(elements).forEach( el => console.log(el));
Comme la méthode Array.from()
est modulable, vous pouvez l’utiliser dans le code es5 comme ceci
var elements = document.getElementsByTagName('abbr');
Array.from(elements).forEach( function(el) {
console.log(el);
});
Pour plus de détails, voir la page MDN .
Pour vérifier support actuel du navigateur .
OU
un autre moyen es2015 consiste à utiliser l'opérateur spread.
[...document.querySelectorAll('abbr')].forEach( el => console.log(el));
Ma solution:
//foreach for nodeList
NodeList.prototype.forEach = Array.prototype.forEach;
//foreach for HTML collection(getElementsByClassName etc.)
HTMLCollection.prototype.forEach = Array.prototype.forEach;
NodeList fait partie de l'API DOM. Examinez les liaisons ECMAScript qui s'appliquent également à JavaScript. http://www.w3.org/TR/DOM-Level-2-Core/ecma-script-binding.html . NodeList et une propriété de longueur en lecture seule et une fonction item (index) pour renvoyer un nœud.
La réponse est, vous devez itérer. Il n'y a pas d'alternative. Foreach ne fonctionnera pas . Je travaille avec des liaisons API Java DOM et ai le même problème.
Recherchez dans le MDN la spécification NodeList.forEach .
NodeList.forEach(function(item, index, nodeList) {
// code block here
});
Dans IE, utilisez la réponse de akuhn :
[].forEach.call(NodeList, function(item, index, array) {
// code block here
});