Sommaire
Les objets NodeList
sont des collections de nœuds comme celles retournées par Node.childNodes
et la méthode querySelectorAll.
Propriétés
- length
- Le nombre de nœuds dans le
NodeList
.
Méthodes
item ( idx )
- Retourne un élément de la liste par son index ou
null
si l'index est en dehors des limites. Équivalent ànodeList[idx]
.
Description
Une collection directe
Dans certains cas, le NodeList
est une collection directe. Cela signifie que les changements effectués dans le DOM sont reflétés dans la collection.
var divs = document.getElementsByTagName( 'div' ); var firstDiv = divs[ 0 ]; // firstDiv.childNodes.length === 2 par instance. firstDiv.appendChild( document.createElement( 'div' ) ); // une autre div est ajoutée comme descendante // le NodeList firstDiv.childNodes est automatiquement mis à jour // firstDiv.childNodes.length === 3 instances maintenant.
Si le NodeList
est la valeur retournée par document.querySelectorAll
, il n'est pas direct.
Pourquoi ne puis-je pas utiliser forEach
ou map
sur un NodeList
?
Les NodeList
s sont utilisés de la même manière que les tableaux et il est donc tentant d'utiliser des méthodes de Array.prototype
sur eux, mais ils ne les implémentent pas.
Le JavaScript a un mécanisme d'héritage basé sur les prototypes pour les objets instanciés (comme les Arrays
) et pour les objets hôtes (comme des NodeLists
). Les instances d'Array
héritent des méthodes des tableaux (comme forEach
ou map
) parce que leur 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 Object.getPrototypeOf
plusieurs fois.)
forEach
, map
et d'autres sont des propriétés propres de l'objet Array.prototype
.
Contrairement aux tableaux, la chaîne de prototypes des NodeLists
ressemble à ce qui suit :
myNodeList --> NodeList.prototype --> Object.prototype --> null
NodeList.prototype
contient la méthode item
, mais aucune méthode de Array.prototype
, elles ne peuvent donc pas être utilisés sur les NodeLists.
Solutions de contournement
Une idée serait d'ajouter des méthodes de Array.prototype
à NodeList.prototype
. Cependant, soyez conscient qu'étendre le DOM est dangereux, surtout dans les vieilles versions d'Internet Explorer (6, 7, 8).
var arrayMethods = Object.getOwnPropertyNames( Array.prototype ); arrayMethods.forEach( attachArrayMethodsToNodeList ); function attachArrayMethodsToNodeList(methodName) { NodeList.prototype[methodName] = Array.prototype[methodName]; }; var divs = document.getElementsByTagName( 'div' ); var firstDiv = divs[ 0 ]; firstDiv.childNodes.forEach(function( divChild ){ divChild.parentNode.style.color = '#0F0'; });
Une autre approche, sans extension du DOM :
var forEach = Array.prototype.forEach; var divs = document.getElementsByTagName( 'div' ); var firstDiv = divs[ 0 ]; forEach.call(firstDiv.childNodes, function( divChild ){ divChild.parentNode.style.color = '#0F0'; });
Notez dans l'exemple ci-dessus que passer un objet hôte (comme un NodeListv
) comme this
à une méthode native (comme forEach
) n'est pas une garantie de bon fonctionnement avec tous les navigateurs et c'est même connu que c'est une cause d'échec avec certains.
Exemple
Il est possible de boucler sur les éléments d'un NodeList
en utilisant :
for (var i = 0; i < myNodeList.length; ++i) { var item = myNodeList[i]; // L'appel de myNodeList.item(i) n'est pas nécessaire en JavaScript }
Ne soyez pas tenté d'utiliser for… in
ou for each… in
pour énumérer les éléments de la liste, car cela énumère également la taille (length
) et les propriétés du NodeList
et cause des erreurs si votre script ne gère que les objets de type element
. De plus, for… in
ne garantit pas de visiter les propriétés dans un ordre particulier.
Les boucles for… of
boucleront correctement sur les NodeList, dans les navigateurs qui supportent for… of
(comme Firefox 13 et plus) :
var list = document.querySelectorAll( 'input[type=checkbox]' ); for (var item of list) { item.checked = true; }
Comment convertir un NodeList
en Array
?
Parfois, il est nécessaire de convertir un objet NodeList
en un Array
, par exemple pour utiliser une méthode spécifique d'Array
. Ci-dessous, un exemple d'une technique de conversion d'un objet NodeList
en un Array
:
var turnObjToArray = function(obj) { return [].map.call(obj, function(element) { return element; }) }; var box = document.querySelectorAll('div'); var listBox = turnObjToArray(box)