Cela me dérange que je ne puisse pas simplement faire document.querySelectorAll(...).map(...)
même dans Firefox 3.6, et je ne trouve toujours pas de réponse, alors j'ai pensé que je posterais sur SO la question de ce blog:
http://blowery.org/2008/08/29/yay-for-queryselectorall-boo-for-staticnodelist/
Est-ce que quelqu'un connaît une raison technique pour laquelle vous n'obtenez pas de tableau? Ou pourquoi ne StaticNodeList pas hérité d'un tableau de manière à ce 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-elle (intentionnellement?) Bloquée en premier lieu?)
Réponses:
Je pense que c'est une décision philosophique du W3C. La conception du DOM W3C [spec] est assez orthogonale à la conception de JavaScript, car le DOM est censé être neutre en termes de plate-forme et de langage.
Les décisions telles que "
getElementsByFoo()
retourne un ordreNodeList
" ou "querySelectorAll()
retourne unStaticNodeList
" sont très intentionnelles, de sorte que les implémentations n'ont pas à se soucier d'aligner leur structure de données retournée en fonction des implémentations dépendantes du langage (comme.map
être disponible sur les tableaux en JavaScript et Ruby, mais pas sur les listes en C #).Le W3C vise bas: ils diront que a
NodeList
devrait contenir une propriété en lecture seule.length
de type unsigned long parce qu'ils pensent que chaque implémentation peut au moins prendre en charge cela , mais ils ne diront pas explicitement que l'[]
opérateur d'index devrait être surchargé pour prendre en charge l'obtention d'éléments positionnels, parce qu'ils ne veulent pas contrecarrer un petit langage pauvre qui veut être implémentégetElementsByFoo()
mais ne peut pas supporter la surcharge des opérateurs. C'est une philosophie répandue présente dans une grande partie de la spécification.John Resig a exprimé une option similaire à la vôtre, à laquelle il ajoute :
Je compatis quelque peu. Si le DOM était écrit spécifiquement avec les fonctionnalités JavaScript à l'esprit, il serait beaucoup moins gênant et plus intuitif à utiliser. En même temps, je comprends les décisions de conception du W3C.
la source
StaticNodeList
en tableau. J'approuverais la réponse de @ mck89 comme la voie à suivre pour convertir unNodeList
/StaticNodeList
en un tableau natif, mais cela échouera dans IE (8 obv) avec une erreur JScript, puisque ces objets sont hébergés / "spéciaux".document
,window
, etc. IE implémente souvent ces « spécialement » (par exemple sous forme d' objets COM) qui parfois ne sont pas conformes à une utilisation normale, de manière petites et subtiles, telles que leArray.prototype.slice.call
bombardement quand donnéStaticNodeList
;)Vous pouvez utiliser l' opérateur de propagation ES2015 (ES6) :
[...document.querySelectorAll('div')]
convertira StaticNodeList en tableau d'éléments.
Voici un exemple d'utilisation.
la source
Array.from(document.querySelectorAll('div')).map(x => console.log(x.innerHTML))
Je ne sais pas pourquoi il renvoie une liste de nœuds au lieu d'un tableau, peut-être parce que, comme getElementsByTagName, il mettra à jour le résultat lorsque vous mettez à jour le DOM. Quoi qu'il en soit, une méthode très simple pour transformer ce résultat en un tableau simple est:
et ensuite vous pouvez faire:
la source
slice
ligne cependant.Juste pour ajouter à ce que Crescent a dit,
Ne fais pas ça! Il n'est pas du tout garanti de fonctionner.
Aucun standard JavaScript ou DOM / BOM ne spécifie que la
NodeList
fonction constructeur existe même en tant quewindow
propriété globale / , ou que leNodeList
retourné parquerySelectorAll
en héritera, ou que son prototype est accessible en écriture, ou que la fonction fonctionneraArray.prototype.map
réellement sur une NodeList.Un NodeList est autorisé à être un «objet hôte» (et en est un, dans IE et certains navigateurs plus anciens). Les
Array
méthodes sont définies comme étant autorisées à fonctionner sur n'importe quel 'objet natif' JavaScript qui expose des valeurs numériques et deslength
propriétés, mais elles ne sont pas obligées de travailler sur des objets hôtes (et dans IE, ce n'est pas le cas).C'est ennuyeux que vous n'obteniez pas toutes les méthodes de tableau sur les listes DOM (toutes, pas seulement StaticNodeList), mais il n'y a pas de moyen fiable de contourner cela. Vous devrez convertir manuellement chaque liste DOM que vous récupérez en un tableau:
la source
new Array(n)
donne juste au terp JS un indice sur la durée du tableau. Cela pourrait lui permettre d'allouer cette quantité d'espace à l'avance, ce qui entraînerait potentiellement une accélération car certaines réallocations de mémoire pourraient être évitées à mesure que le tableau se développe. Je ne sais pas si cela aide réellement les navigateurs modernes ... Je soupçonnerais pas mesurable.Je pense que vous pouvez simplement suivre
Cela fonctionne parfaitement pour moi
la source
C'est une option que je voulais ajouter à la gamme d'autres possibilités suggérées par d'autres ici. Il est destiné uniquement au plaisir intellectuel et n'est pas conseillé .
Juste pour le plaisir , voici un moyen de "forcer"
querySelectorAll
à s'agenouiller et à s'incliner devant vous:Maintenant, ça fait du bien de passer à travers cette fonction, en lui montrant qui est le patron. Maintenant, je ne sais pas ce qui est mieux, créer un tout nouveau wrapper de fonction nommée , puis faire en sorte que tout votre code utilise ce nom étrange (à peu près de style jQuery) ou remplace la fonction comme ci-dessus une fois pour que le reste de votre code puisse toujours pour utiliser le nom de la méthode DOM d'origine
querySelectorAll
.la source