J'ai une fonction Javascript qui accepte une liste de nœuds HTML, mais elle attend un tableau Javascript (il exécute certaines méthodes Array là-dessus) et je veux lui donner la sortie Document.getElementsByTagName
qui renvoie une liste de nœuds DOM.
Au départ, j'ai pensé à utiliser quelque chose de simple comme:
Array.prototype.slice.call(list,0)
Et cela fonctionne très bien dans tous les navigateurs, sauf bien sûr Internet Explorer qui renvoie l'erreur "Objet JScript attendu", car apparemment la liste des nœuds DOM renvoyée par les Document.getElement*
méthodes n'est pas un objet JScript suffisant pour être la cible d'un appel de fonction.
Avertissements: cela ne me dérange pas d'écrire du code spécifique à Internet Explorer, mais je ne suis pas autorisé à utiliser des bibliothèques Javascript telles que JQuery car j'écris un widget à intégrer dans un site Web tiers et je ne peux pas charger de bibliothèques externes qui créera un conflit pour les clients.
Mon dernier effort consiste à parcourir la liste des nœuds DOM et à créer moi-même un tableau, mais y a-t-il une meilleure façon de le faire?
la source
Réponses:
Les listes de nœuds sont des objets hôtes , l'utilisation de la
Array.prototype.slice
méthode sur les objets hôtes n'est pas garantie de fonctionner, la spécification ECMAScript indique:Je vous recommande de créer une fonction simple pour parcourir le
NodeList
et ajouter chaque élément existant à un tableau:METTRE À JOUR:
Comme d'autres réponses le suggèrent, vous pouvez désormais utiliser dans les environnements modernes la syntaxe de diffusion ou la
Array.from
méthode:Mais en y réfléchissant, je suppose que le cas d'utilisation le plus courant pour convertir une NodeList en Array est de l'itérer, et maintenant l'
NodeList.prototype
objet a laforEach
méthode nativement , donc si vous êtes dans un environnement moderne, vous pouvez l'utiliser directement, ou avoir un pollyfill.la source
array[i] = obj[i]
au lieu dearray.push(obj[i])
?obj.length
autre chose qu'une valeur entière?Dans es6, vous pouvez simplement utiliser comme suit:
Opérateur de propagation
En utilisant
Array.from
plus de références sur https://developer.mozilla.org/en-US/docs/Web/API/NodeList
la source
Array.from()
: DArray.from
fonctionne que, car TS transpile cela versnodelist.slice
- ce qui n'est pas pris en charge.Array.from
spread
est utilisé.En utilisant spread (ES2015) , c'est aussi simple que:
[...document.querySelectorAll('p')]
(facultatif: utilisez Babel pour transpiler le code ES6 ci-dessus en syntaxe ES5)
Essayez-le dans la console de votre navigateur et voyez la magie:
la source
Utilisez cette astuce simple
la source
Array.prototype.slice
(ou[].slice
comme vous le dites)? À titre de note, j'aimerais faire remarquer que l'erreur spécifique à IE que j'ai documentée dans le Q se produit dans IE 8 ou une version inférieure, où ellemap
n'est de toute façon pas implémentée. Dans IE 9 ( « mode standard ») ou plus, à la foisslice
etmap
réussir de la même manière.Bien que ce ne soit pas vraiment un shim approprié, puisqu'il n'y a pas de spécification nécessitant de travailler avec des éléments DOM, j'en ai créé une pour vous permettre de l'utiliser
slice()
de cette manière: https://gist.github.com/brettz9/6093105MISE À JOUR : Quand j'ai soulevé cela avec l'éditeur de la spécification DOM4 (demandant s'ils pouvaient ajouter leurs propres restrictions aux objets hôtes (de sorte que la spécification obligerait les implémenteurs à convertir correctement ces objets lorsqu'ils sont utilisés avec des méthodes de tableau) au-delà de la spécification ECMAScript qui avait autorisé pour l'indépendance de l'implémentation), il a répondu que "les objets hôtes sont plus ou moins obsolètes par ES6 / IDL." Je vois par http://www.w3.org/TR/WebIDL/#es-array que les spécifications peuvent utiliser cet IDL pour définir des "objets de tableau de plate-forme" mais http://www.w3.org/TR/domcore/ ne le fait pas 'ne semble pas utiliser le nouvel IDL pour (qui hérite de Array.prototype) est utilisé pour (et est maintenant obsolète au profit du seul élément qui l'utilise encore,
HTMLCollection
(bien qu'il semble que cela puisse être le cas carElement.attributes
il déclare seulement explicitement qu'il utilise WebIDL pour DOMString et DOMTimeStamp). Je vois[ArrayClass]
NodeList
NamedNodeMap
Element.attributes
). Dans tous les cas, on dirait que ça va devenir standard. L'ES6Array.from
pourrait également être plus pratique pour de telles conversions que d'avoir à spécifierArray.prototype.slice
et plus sémantiquement clair que[].slice()
(et la forme plus courte,Array.slice()
(un "tableau générique"), n'est pas devenue, pour autant que je sache, un comportement standard).la source
Aujourd'hui, en 2018, nous pourrions utiliser l'ECMAScript 2015 (6e édition) ou l'ES6, mais tous les navigateurs ne peuvent pas le comprendre (par exemple, IE ne comprend pas tout). Si vous le souhaitez, vous pouvez utiliser ES6 comme suit:
var array = [... NodeList];
( comme opérateur de diffusion ) ouvar array = Array.from(NodeList);
.Dans les autres cas (si vous ne pouvez pas utiliser ES6), vous pouvez utiliser le moyen le plus court pour convertir un
NodeList
enArray
:var array = [].slice.call(NodeList, 0);
.Par exemple:
Mais si vous voulez parcourir la
DOM
liste des nœuds facile que, vous n'avez pas besoin de convertir unNodeList
à unArray
. Il est possible de parcourir les éléments enNodeList
utilisant:Ne soyez pas tenté d'utiliser
for...in
oufor each...in
d'énumérer les éléments de la liste, car cela énumérera également la longueur et les propriétés de l'élémentNodeList
et provoquera des erreurs si votre script suppose qu'il ne doit traiter que des objets élément. En outre, ilfor..in
n'est pas garanti de visiter les propriétés dans un ordre particulier.for...of
les boucles boucleront correctement sur les objets NodeList.Voir aussi:
la source
Cela devrait fonctionner, traverser le navigateur et obtenir tous les nœuds "élément".
la source