Pourquoi n'document.querySelectorAll retour d'un StaticNodeList plutôt que d'un véritable Tableau?
Il m'énerve que je ne peux pas juste faire document.querySelectorAll(...).map(...)
même dans Firefox 3.6, et je n'ai toujours pas de réponse, donc je pensais que je cross-post sur DONC la question de ce blog:
http://blowery.org/2008/08/29/yay-for-queryselectorall-boo-for-staticnodelist/
Personne ne sait d'une raison technique pour laquelle vous n'obtenez pas un Tableau? Ou pourquoi un StaticNodeList ne pas hériter d'un Tableau de telle manière que vous pouvez utiliser map
, concat
, etc?
(BTW si c'est juste une fonction que vous voulez, vous pouvez faire quelque chose comme NodeList.prototype.map = Array.prototype.map;
...mais encore une fois, pourquoi cette fonctionnalité est (intentionnellement?) bloqué en premier lieu?)
- En fait getElementsByTagName ne pas retourner un Tableau, mais une collection, et si vous voulez l'utiliser comme un Tableau (avec des méthodes comme concat etc.) vous devez convertir votre collection dans un Tableau en faisant une boucle et copier chaque élément de la collection dans un Tableau. Jamais personne ne s'est plaint à ce sujet.
Vous devez vous connecter pour publier un commentaire.
Je crois que c'est une décision philosophique de la W3C. La conception du DOM du W3C [spec] est tout à fait perpendiculaire à la conception de JavaScript, le DOM est signifiait à plate-forme et du langage neutre.
Décisions comme "
getElementsByFoo()
renvoie d'un ordreNodeList
" ou "querySelectorAll()
renvoie uneStaticNodeList
" sont très intentionnel, ainsi que les implémentations n'avez pas à vous soucier de l'alignement de leurs retourné structure de données basée sur la fonction de la langue dans les implémentations (comme.map
être disponibles sur les Tableaux en JavaScript et Ruby, mais pas sur les Listes en C#).Le W3C but faible: ils disent une
NodeList
doit contenir un readonly.length
de la propriété de type unsigned long parce qu'ils croient que chaque mise en œuvre à que, mais ils ne disent pas explicitement que le[]
l'indice de l'opérateur doit être surchargé en charge l'obtention de position des éléments, parce qu'ils ne veulent pas entraver le pauvre petit langage qui vient qui veut mettre en œuvregetElementsByFoo()
mais ne peut pas supporter la surcharge d'opérateur. C'est une conséquence courante de la philosophie dans une grande partie de la spécification.John Resig a exprimé une option similaire que le vôtre, à qui il ajoute:
Je ne peu faire preuve d'empathie. Si le DOM a été écrit spécifiquement avec les fonctions JavaScript à l'esprit, il sera beaucoup moins difficile et plus intuitif à utiliser. En même temps, je comprends le W3C, les décisions de conception.
StaticNodeList
à un tableau. Je partage @mck89 réponse comme la voie à suivre pour la conversion d'unNodeList
/StaticNodeList
à un Tableau natif, mais qui échoue dans IE (8 obv) avec une JScript erreur, puisque ces objets sont hébergés/"spécial".document
,window
, etc. IE mettent souvent en œuvre des ces "spécialement" (par exemple en tant qu'objets COM) que, parfois, ne sont pas conformes à une utilisation normale, dans les petites et subtile, commeArray.prototype.slice.call
attentat lors d'uneStaticNodeList
😉Vous pouvez utiliser ES2015 (ES6) la propagation de l'opérateur:
[...document.querySelectorAll('div')]
va convertir StaticNodeList de Tableau d'éléments.
Voici un exemple sur la façon de l'utiliser.
JS:
HTML:
Array.from(document.querySelectorAll('div')).map(x => console.log(x.innerHTML))
Je ne sais pas pourquoi elle retourne une liste de noeud au lieu d'un tableau, peut-être parce que, comme getElementsByTagName elle sera mise à jour lors de la mise à jour du DOM. De toute façon une méthode très simple pour transformer ce résultat dans un tableau simple est:
et ensuite vous pouvez faire:
slice
ligne.Juste pour ajouter à ce Croissant-dit,
Ne le faites pas! Il n'est pas garanti pour fonctionner.
Pas de JavaScript et DOM/NOMENCLATURE standard précise que l'
NodeList
constructeur-même existe en tant que global/window
des biens, ou que leNodeList
retourné parquerySelectorAll
va hériter d'elle, ou que son prototype est accessible en écriture, ou que la fonctionArray.prototype.map
sera effectivement travailler sur une NodeList.Une NodeList est autorisé à être un ‘d'accueil ' objet’ (et il est un, en IE et certains anciens navigateurs). Le
Array
méthodes sont définies comme étant autorisés à fonctionner sur n'importe quel JavaScript native de l'objet " qui expose numérique etlength
propriétés, mais ils ne sont pas amenés à travailler sur des objets hôte (et dans IE, ils ne le font pas).C'est ennuyeux que vous n'obtenez pas toutes les méthodes de tableau sur les DOM listes de tous, et pas seulement StaticNodeList), mais il n'y a aucun moyen fiable autour d'elle. Vous aurez à convertir tous les DOM liste, vous obtenez de retour à un Tableau manuellement:
new Array(n)
donne juste le JS terp une indication sur la durée de la matrice va finir. Qui pourrait lui permettre d'allouer que la quantité d'espace à l'avance, ce qui pourrait potentiellement entraîner une accélération comme la mémoire des réaffectations pourrait être évitée, comme le tableau de pousse. Je ne sais pas si cela aide réellement dans les navigateurs modernes bien... je dirais pas de façon mesurable.Je pense que vous pouvez tout simplement faire à la suite
Il fonctionne parfaitement pour moi
C'est une option que je voulais ajouter à la gamme d'autres possibilités suggérées par d'autres ici. Il est destiné pour le plaisir intellectuel et est pas conseillé.
Juste pour le plaisir, ici est une façon de "forcer"
querySelectorAll
à s'agenouiller et se prosterner devant vous:Maintenant il se sent bien à l'étape de tous les plus de cette fonction, montrer qui est le patron.
Maintenant, je ne sais pas ce qui est mieux, la création d'un nouveau nommé fonction wrapper et alors votre code utiliser ce nom bizarre (assez bien jQuery-style) ou de remplacer la fonction comme ci-dessus une fois pour le reste de votre code devrait toujours être en mesure d'utiliser l'original DOM nom de la méthode
querySelectorAll
.