102 votes

Pourquoi la liste de nœuds n'a-t-elle pas de forEach ?

Je travaillais sur un court script pour changer <abbr> mais a constaté que le texte interne des éléments nodelist n'a pas de forEach méthode. Je sais que nodelist n'hérite pas de Array mais ne semble-t-il pas que forEach serait une méthode utile ? Y a-t-il un problème d'implémentation particulier dont je ne suis pas au courant et qui empêche l'ajout d'une méthode de gestion de l'information dans le système ? forEach a nodelist ?

Note : Je suis conscient que Dojo et jQuery ont tous les deux forEach sous une forme ou une autre pour leurs listes de nœuds. Je ne peux utiliser ni l'un ni l'autre en raison de leurs limitations.

6 votes

62voto

akuhn Points 12241

Vous pouvez faire

Array.prototype.forEach.call (nodeList, function (node) {

    // Your code here.

} );

3 votes

Array.prototype.forEach.call peut être raccourci en [].forEach.call

8 votes

@CodeBrauer : ce n'est pas seulement du shortening. Array.prototype.forEach.call il crée un tableau vide et utilise sa fonction forEach méthode.

34voto

sbr Points 1205

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.  

  });

Note : Il s'agit juste d'une liste/réseau 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

22 votes

Ou juste faire Array.prototype.forEach.call(nodeList, fun) .

0 votes

Je suggère également d'aliaser la fonction forEach de telle sorte que : var forEach = Array.prototype.forEach.call(nodeList, callback); . Maintenant, vous pouvez simplement appeler forEach(nodeList, callback);

19voto

Matt Lo Points 1470

En bref, la mise en œuvre de cette méthode constitue un conflit de conception.

Du MDN :

Pourquoi ne puis-je pas utiliser forEach ou map sur une NodeList ?

Les NodeList sont utilisées comme des tableaux et il serait tentant d'utiliser les méthodes de utiliser les méthodes Array.prototype sur eux. C'est cependant impossible.

JavaScript dispose d'un mécanisme d'héritage basé sur les prototypes. Un tableau héritent des méthodes de tableau (telles que forEach ou map) car leur chaîne de prototypes se présente comme suit chaîne de prototypes 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 autres sont des propriétés propres à l'objet Array.prototype d'un tableau.

Contrairement aux tableaux, la chaîne de prototypes de NodeList ressemble à ce qui suit :

myNodeList --> NodeList.prototype --> Object.prototype --> null

NodeList.prototype contient la méthode item, mais aucune méthode de type Array.prototype, donc elles ne peuvent pas être utilisées sur les NodeLists.

Fuente: https://developer.mozilla.org/en-US/docs/DOM/NodeList (faire défiler jusqu'à Pourquoi ne puis-je pas utiliser forEach ou map sur une NodeList ? )

8 votes

Donc, puisque c'est une liste, pourquoi est-elle conçue de cette façon ? Qu'est-ce qui les empêchait de faire des chaînes : myNodeList --> NodeList.prototype --> Array.prototype --> Object.prototype --> null ?

15voto

AlexTR Points 119

Si vous souhaitez utiliser forEach sur NodeList, copiez simplement cette fonction depuis Array :

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

C'est tout, maintenant vous pouvez l'utiliser de la même manière que pour Array :

document.querySelectorAll('td').forEach(function(o){
   o.innerHTML = 'text';
});

4 votes

Sauf que la mutation des classes de base n'est pas très explicite pour le lecteur moyen. En d'autres termes, dans une partie du code, vous devez vous souvenir de chaque personnalisation apportée aux objets de base du navigateur. Se fier à la documentation MDN n'est plus utile car les objets ont changé de comportement par rapport à la norme. Il est préférable d'appliquer explicitement le prototype au moment de l'appel afin que le lecteur puisse facilement réaliser que forEach est une idée empruntée et non quelque chose qui fait partie de la définition du langage. Voir la réponse de @akuhn ci-dessus.

0 votes

@Sukima s'est égaré dans de mauvaises prémisses. Dans ce cas spécifique, l'approche donnée permet à NodeList de se comporter comme prévu par le développeur. C'est la façon la plus appropriée de résoudre le problème de classe système. (NodeList semble être inachevé et devrait être corrigé dans les futures versions du langage).

1 votes

Maintenant que NodeList.forEach existe, cela devient un polyfill hilarant et simple !

0voto

Suresh Koya Points 726

NodeList fait partie de l'API DOM. Regardez les liaisons ECMAScript qui s'appliquent également à JavaScript. http://www.w3.org/TR/DOM-Level-2-Core/ecma-script-liaison.html . La nodeList et une propriété de longueur en lecture seule et la fonction item(index) pour retourner un noeud.

La réponse est que vous devez itérer. Il n'y a pas d'alternative. Foreach ne fonctionnera pas. Je travaille avec des liaisons Java DOM API et j'ai le même problème.

0 votes

Mais y a-t-il une raison particulière pour laquelle il ne devrait pas être mis en œuvre ? jQuery et Dojo l'ont implémenté dans leurs propres bibliothèques.

2 votes

Mais en quoi est-ce un conflit de conception ?

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X