queryselectorall queryselector attribute javascript dom css-selectors

javascript - attribute - ¿Por qué document.querySelectorAll devuelve StaticNodeList en lugar de una matriz real?



queryselectorall foreach (5)

Creo que es una decisión filosófica del W3C. El diseño del W3C DOM [spec] es bastante ortogonal al diseño de JavaScript, ya que DOM está destinado a ser plataforma y lenguaje neutral.

Decisiones como " getElementsByFoo() devuelve un NodeList ordenado" o " querySelectorAll() devuelve StaticNodeList " son muy intencionales, por lo que las implementaciones no tienen que preocuparse de alinear su estructura de datos devuelta basada en implementaciones dependientes del lenguaje (como .map estando disponible en Arrays en JavaScript y Ruby, pero no en Listas en C #).

El objetivo del W3C es bajo: dirán que una NodeList debería contener una propiedad .length de tipo unsigned long porque creen que cada implementación puede al menos soportar eso , pero no dirán explícitamente que el operador de índice [] debería estar sobrecargado a soporte para obtener elementos posicionales, porque no quieren bloquear un poco de lenguaje pobre que viene y quiere implementar getElementsByFoo() pero no puede soportar la sobrecarga del operador. Es una filosofía prevaleciente presente en gran parte de las especificaciones.

John Resig ha expresado una opción similar a la suya, a la que agrega :

Mi argumento no es tanto que NodeIterator no sea muy similar a DOM, sino que no es muy parecido a JavaScript. No aprovecha las características presentes en el lenguaje JavaScript y las usa de la mejor manera posible ...

De alguna manera siento empatía. Si el DOM se escribió específicamente con las características de JavaScript en mente, sería mucho menos incómodo y más intuitivo de usar. Al mismo tiempo entiendo las decisiones de diseño del W3C.

Me molesta que no puedo hacer document.querySelectorAll(...).map(...) incluso en Firefox 3.6, y todavía no puedo encontrar una respuesta, así que pensé en publicar de forma cruzada en ASÍ la pregunta de este blog:

http://blowery.org/2008/08/29/yay-for-queryselectorall-boo-for-staticnodelist/

¿Alguien sabe de una razón técnica por la que no obtienes un Array? ¿O por qué StaticNodeList no hereda de una matriz de forma que pueda usar map , concat , etc.?

(Por cierto, si solo desea una función, puede hacer algo como NodeList.prototype.map = Array.prototype.map; ... pero nuevamente, ¿por qué esta funcionalidad (¿intencionalmente?) Está bloqueada en primer lugar?)


Creo que simplemente puedes hacer lo siguiente

Array.prototype.map.call(document.querySelectorAll(...), function(...){...});

Funciona perfecto para mí


No sé por qué devuelve una lista de nodos en lugar de una matriz, tal vez porque, como getElementsByTagName, actualizará el resultado cuando actualice el DOM. De todos modos, un método muy simple para transformar ese resultado en una matriz simple es:

Array.prototype.slice.call(document.querySelectorAll(...));

y luego puedes hacer:

Array.prototype.slice.call(document.querySelectorAll(...)).map(...);


Puede usar el operador de propagación ES2015 (ES6):

[...document.querySelectorAll(''div'')]

convertirá StaticNodeList en una matriz de elementos.

Aquí hay un ejemplo sobre cómo usarlo.

[...document.querySelectorAll(''div'')].map(x => console.log(x.innerHTML))

<div>Text 1</div> <div>Text 2</div>


Solo para agregar a lo que Crescent dijo,

si solo desea una función, puede hacer algo como NodeList.prototype.map = Array.prototype.map

No hagas esto! No está garantizado que funcione.

Ningún JavaScript o estándar DOM / BOM especifica que la NodeList constructor NodeList existe incluso como una propiedad global / de window , o que la NodeList devuelta por querySelectorAll heredará de ella, o que su prototipo es escribible, o que la función Array.prototype.map realmente funcionará en una NodeList.

A NodeList se le permite ser un ''objeto host'' (y es uno, en IE y algunos navegadores más antiguos). Los métodos Array se definen como permitidos para operar en cualquier ''objeto nativo'' de JavaScript que exhiba las propiedades numéricas y de length , pero no están obligados a trabajar en objetos host (y en IE, no lo hacen).

Es molesto que no obtenga todos los métodos de matriz en listas DOM (todos ellos, no solo StaticNodeList), pero no hay una manera confiable de eludirlo. Tendrá que convertir cada lista DOM que regrese a una matriz manualmente:

Array.fromList= function(list) { var array= new Array(list.length); for (var i= 0, n= list.length; i<n; i++) array[i]= list[i]; return array; }; Array.fromList(element.childNodes).forEach(function() { ... });