Me molesta que no pueda hacerlo document.querySelectorAll(...).map(...)
ni siquiera en Firefox 3.6, y todavía no puedo encontrar una respuesta, así que pensé en hacer una publicación cruzada en SO 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 una matriz? O por qué un StaticNodeList no hereda de un Array de tal manera que podría usarmap
, concat
etc?
(Por cierto, si es solo una función lo que desea, puede hacer algo como NodeList.prototype.map = Array.prototype.map;
... pero nuevamente, ¿por qué esta funcionalidad (¿intencionalmente?) Está bloqueada en primer lugar?)
Respuestas:
Creo que es una decisión filosófica del W3C. El diseño del DOM de W3C [especificación] es bastante ortogonal al diseño de JavaScript, ya que el DOM se entiende a ser una plataforma y un lenguaje neutro.
Decisiones como "
getElementsByFoo()
devuelve un pedidoNodeList
" o "querySelectorAll()
devuelve unStaticNodeList
" son muy intencionales, por lo que las implementaciones no tienen que preocuparse por alinear su estructura de datos devueltos según las implementaciones dependientes del lenguaje (como.map
estar disponible en Arrays en JavaScript y Ruby, pero no en listas en C #).El W3C apunta bajo: dirán que a
NodeList
debería contener una propiedad de solo lectura.length
de tipo unsigned long porque creen que cada implementación puede al menos admitir eso , pero no dirán explícitamente que el[]
operador de índice debería estar sobrecargado para admitir la obtención de elementos posicionales, porque no quieren obstaculizar un pequeño lenguaje deficiente que aparece y que quiere implementargetElementsByFoo()
pero no puede soportar la sobrecarga del operador. Es una filosofía predominante presente en gran parte de la especificación.John Resig ha expresado una opción similar a la suya, a la que agrega :
Siento cierta empatía. Si el DOM se escribió específicamente con las funciones de JavaScript en mente, sería mucho menos incómodo y más intuitivo de usar. Al mismo tiempo, comprendo las decisiones de diseño del W3C.
fuente
StaticNodeList
en una matriz. Apoyaría la respuesta de @ mck89 como el camino a seguir para convertir unNodeList
/StaticNodeList
a un Array nativo, pero eso fallará en IE (8 obv) con un error de JScript, ya que esos objetos están alojados / "especiales".document
,window
, etc. IE menudo implementa estos "especial" (por ejemplo, como objetos COM) que a veces no son conformes con el uso normal, en formas pequeñas y sutiles, tales comoArray.prototype.slice.call
el bombardeo cuando se les da unaStaticNodeList
;)Puede utilizar el operador de propagación ES2015 (ES6) :
[...document.querySelectorAll('div')]
convertirá StaticNodeList en una matriz de elementos.
A continuación, se muestra un ejemplo de cómo utilizarlo.
fuente
Array.from(document.querySelectorAll('div')).map(x => console.log(x.innerHTML))
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:
y luego puedes hacer:
fuente
slice
embargo, +1 para la línea.Solo para agregar a lo que dijo Crescent,
¡No hagas esto! No está garantizado que funcione.
Ningún estándar JavaScript o DOM / BOM especifica que la
NodeList
función de constructor existe incluso como unawindow
propiedad / global , o que laNodeList
devuelta porquerySelectorAll
heredará de ella, o que su prototipo es modificable, o que la funciónArray.prototype.map
realmente funcionará en una NodeList.Una NodeList puede ser un 'objeto de host' (y es uno, en IE y en algunos navegadores más antiguos). Los
Array
métodos se definen como permitidos para operar en cualquier 'objeto nativo' de JavaScript que exponga numérico ylength
propiedades, pero no es necesario que funcionen en objetos host (y en IE, no lo hacen).Es molesto que no obtenga todos los métodos de matriz en las listas DOM (todos ellos, no solo StaticNodeList), pero no hay una forma confiable de evitarlo. Tendrá que convertir todas las listas DOM que obtenga a una matriz manualmente:
fuente
new Array(n)
simplemente le da al terp de JS una pista sobre cuánto tiempo va a terminar la matriz. Eso podría permitirle asignar esa cantidad de espacio por adelantado, lo que podría resultar en una aceleración, ya que algunas reasignaciones de memoria podrían evitarse a medida que la matriz crece. Sin embargo, no sé si realmente ayuda en los navegadores modernos ... sospecho que no es mensurable.Creo que simplemente puedes seguir
Funciona perfecto para mi
fuente
Esta es una opción que quería agregar a la gama de otras posibilidades sugeridas por otros aquí. Está destinado únicamente a la diversión intelectual y no se recomienda .
Solo por diversión , aquí hay una manera de "forzar"
querySelectorAll
a arrodillarse e inclinarse ante usted:Ahora se siente bien pasar por encima de esa función, mostrándole quién es el jefe. Ahora no sé qué es mejor, crear un envoltorio de función con nombre completamente nuevo y luego hacer que todo su código use ese nombre extraño (casi al estilo jQuery) o anule la función como la anterior una vez para que el resto de su código aún pueda para usar el nombre del método DOM original
querySelectorAll
.fuente