102 votes

Comment parcourir tous les éléments retournés par getElementsByTagName

Je essaie de parcourir tous les éléments renvoyés par getElementsByTagName("input") en utilisant forEach. Des idées pourquoi cela ne fonctionne pas dans FF, Chrome ou IE?

            function ShowResults(value, index, ar) {
                alert(index);
            }
            var input = document.getElementsByTagName("input");
            alert(input.length);
            input.forEach(ShowResults);

120voto

Dvir Points 2998

Vous devez convertir la liste de nœuds en un tableau avec ceci :

<html>
    <head>
    </head>
    <body>
        <input type="text" value="" />
        <input type="text" value="" />
        <script>
            function ShowResults(value, index, ar) {
                alert(index);
            }
            var input = document.getElementsByTagName("input");
            var inputList = Array.prototype.slice.call(input);
            alert(inputList.length);
            inputList.forEach(ShowResults);
        </script>
    </body>
</html>

ou utilisez une boucle for.

for(let i = 0;i < input.length; i++)
{
    ShowResults(input[i].value);
}

et changez la fonction ShowResults en :

function ShowResults(value) {
   alert(value);
}

Pourquoi devons-nous faire cela ?
Certains objets en JavaScript ressemblent à un tableau, mais ils n'en sont pas un. Cela signifie généralement qu'ils ont un accès indexé et une propriété de longueur, mais aucune des méthodes de tableau. Les exemples incluent la variable spéciale arguments, les listes de nœuds DOM et les chaînes. Les objets ressemblant à des tableaux et les méthodes génériques donnent des conseils pour travailler avec des objets ressemblant à des tableaux. source

MISE À JOUR du 07.10.2019
Aujourd'hui avec ES6, vous pouvez utiliser [...inputList].forEach, ou Array.from(inputList)

74voto

janaspage Points 1216

Hourra, ES6:

const children = [...parent.getElementsByTagName('tag')];
children.forEach((child) => { /* Faire quelque chose; */ });

Doc MDN pour l'opérateur Spread (...)

34voto

CertainPerformance Points 110949

getElementsByTagName renvoie une HTMLCollection, qui n'a pas de méthode forEach. Mais il existe une astuce simple qui vous permettra d'itérer avec forEach sans créer un tableau intermédiaire : utilisez plutôt querySelectorAll. querySelectorAll renvoie une NodeList, et les navigateurs modernes ont une méthode NodeList.prototype.forEach :

document.querySelectorAll('input')
  .forEach((input) => {
    console.log(input.value);
  });

Un autre avantage d'utiliser querySelectorAll est qu'il accepte des sélecteurs CSS séparés par des virgules, beaucoup plus flexibles et précis que les simples noms de balises. Par exemple, le sélecteur

.container1 > span, .container2 > span

ne correspondra qu'aux span qui sont des enfants d'éléments avec une classe container1 ou container2 :

document.querySelectorAll('.container1 > span, .container2 > span')
  .forEach((span) => {
    span.classList.add('highlight');
  });

.highlight {
  background-color: yellow;
}

  foo
  bar

  baz

  buzz

Si vous souhaitez utiliser NodeList.prototype.forEach sur des navigateurs anciens qui n'ont pas cette méthode intégrée, il suffit d'ajouter un polyfill. Le code suivant fonctionnera sur IE11 :

// Polyfill:
if (window.NodeList && !NodeList.prototype.forEach) {
  NodeList.prototype.forEach = function(callback, thisArg) {
    thisArg = thisArg || window;
    for (var i = 0; i < this.length; i++) {
      callback.call(thisArg, this[i], i, this);
    }
  };
}

// Main code:
document.querySelectorAll('.container1 > span, .container2 > span')
  .forEach(function(span) {
    span.classList.add('highlight');
  });

.highlight {
  background-color: yellow;
}

  foo
  bar

  baz

  buzz

10voto

grape_mao Points 1113

Parce que input n'est pas un tableau, c'est un HTMLCollection. Utiliser une boucle for serait mieux.

Et comme les HTMLCollections sont des objets ressemblant à des tableaux, vous pouvez call Array#forEach dessus comme ceci

Array.prototype.forEach.call(input, ShowResults);

9voto

Naman Sancheti Points 149

La raison pour laquelle cela ne fonctionne pas est que 'getElementsByTagName' renvoie un objet de type tableau (Array-like) plutôt qu'un tableau réel. Si vous n'êtes pas au courant, voici à quoi ils ressemblent tous les deux :-

var realArray = ['a', 'b', 'c'];
var arrayLike = {
  0: 'a',
  1: 'b',
  2: 'c',
  length: 3
};

Ainsi, comme les objets de type tableau (Array-like) héritent de 'Object.prototype' au lieu de 'Array.prototype', cela signifie que les objets de type tableau (Array-like) ne peuvent pas accéder aux méthodes de prototype Array courantes comme forEach(), push(), map(), filter(), et slice().

J'espère que cela vous a aidé!

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