Tengo una función de Javascript que acepta una lista de nodos HTML, pero espera una matriz de Javascript (ejecuta algunos métodos de matriz en eso) y quiero alimentarla con la salida Document.getElementsByTagName
que devuelve una lista de nodos DOM.
Inicialmente pensé en usar algo simple como:
Array.prototype.slice.call(list,0)
Y eso funciona bien en todos los navegadores, excepto, por supuesto, en Internet Explorer que devuelve el error "Se esperaba un objeto JScript", ya que aparentemente la lista de nodos DOM devuelta por los Document.getElement*
métodos no es un objeto JScript suficiente para ser el objetivo de una llamada de función.
Advertencias: no me importa escribir código específico de Internet Explorer, pero no puedo usar ninguna biblioteca Javascript como JQuery porque estoy escribiendo un widget para incrustarlo en un sitio web de terceros y no puedo cargar bibliotecas externas que creará conflictos para los clientes.
Mi último esfuerzo es iterar sobre la lista de nodos DOM y crear una matriz yo mismo, pero ¿hay una manera mejor de hacerlo?
fuente
Respuestas:
NodeLists son objetos host ,
Array.prototype.slice
no se garantiza que el método en objetos host funcione, la Especificación ECMAScript establece:Le recomendaría que haga una función simple para iterar sobre
NodeList
y agregar cada elemento existente a una matriz:ACTUALIZAR:
Como sugieren otras respuestas, ahora puede usar en entornos modernos la sintaxis de propagación o el
Array.from
método:Pero pensándolo bien, supongo que el caso de uso más común para convertir un NodeList en un Array es iterar sobre él, y ahora el
NodeList.prototype
objeto tiene elforEach
método de forma nativa , por lo que si se encuentra en un entorno moderno, puede usarlo directamente o tener un pollyfill.fuente
array[i] = obj[i]
lugar dearray.push(obj[i])
?obj.length
cualquier otra cosa que no sea un valor entero?En es6 puede usar lo siguiente:
Operador de propagación
Utilizando
Array.from
más referencias en https://developer.mozilla.org/en-US/docs/Web/API/NodeList
fuente
Array.from()
: DArray.from
funciona, ya que TS transpila esto anodelist.slice
, lo cual no es compatible.Array.from
spread
se usará.Usar spread (ES2015) es tan fácil como:
[...document.querySelectorAll('p')]
(opcional: use Babel para transpilar el código ES6 anterior a la sintaxis ES5)
Pruébelo en la consola de su navegador y vea la magia:
fuente
Usa este sencillo truco
fuente
Array.prototype.slice
(o[].slice
como lo dice)? Como nota, me gustaría comentar que el error específico de IE que documenté en la Q ocurre en IE 8 o inferior, dondemap
no está implementado de todos modos. En IE 9 ("modo estándar") o superior, ambosslice
ymap
tienen éxito de la misma manera.Si bien no es realmente una corrección adecuada, ya que no hay ninguna especificación que requiera trabajar con elementos DOM, hice una para permitirle usar
slice()
de esta manera: https://gist.github.com/brettz9/6093105ACTUALIZACIÓN : cuando planteé esto con el editor de la especificación DOM4 (preguntando si podrían agregar sus propias restricciones a los objetos del host (de modo que la especificación requiera que los implementadores conviertan correctamente estos objetos cuando se usan con métodos de matriz) más allá de la especificación ECMAScript que tenía permitido para la implementación-independencia), respondió que "los objetos de host son más o menos obsoletos según ES6 / IDL". Veo por http://www.w3.org/TR/WebIDL/#es-array que las especificaciones pueden usar este IDL para definir "objetos de matriz de plataforma" pero http://www.w3.org/TR/domcore/ doesn no parece estar usando el nuevo IDL para
HTMLCollection
(aunque parece que podría estar haciéndoloElement.attributes
porque solo indica explícitamente que está usando WebIDL para DOMString y DOMTimeStamp). Yo veo[ArrayClass]
(que hereda de Array.prototype) se usa paraNodeList
(yNamedNodeMap
ahora está en desuso en favor del único elemento que todavía lo usaríaElement.attributes
). En cualquier caso, parece que se convertirá en estándar. El ES6Array.from
también podría ser más conveniente para tales conversiones que tener que especificarArray.prototype.slice
y más claro semánticamente que[].slice()
(y la forma más corta,Array.slice()
(una "matriz genérica"), hasta donde yo sé, no se ha convertido en un comportamiento estándar).fuente
Hoy, en 2018, podríamos usar ECMAScript 2015 (sexta edición) o ES6, pero no todos los navegadores pueden entenderlo (por ejemplo, IE no lo entiende todo). Si lo desea, puede usar ES6 de la siguiente manera:
var array = [... NodeList];
( como operador de propagación ) ovar array = Array.from(NodeList);
.En otro caso (si no puede usar ES6) puede usar la forma más corta de convertir un
NodeList
en unArray
:var array = [].slice.call(NodeList, 0);
.Por ejemplo:
Pero si solo desea iterar sobre la
DOM
lista de nodos de manera fácil, entonces no necesita convertirNodeList
a enArray
. Es posible recorrer los elementos en unNodeList
uso:No se sienta tentado a utilizar
for...in
ofor each...in
enumerar los elementos de la lista, ya que eso también enumerará la longitud y las propiedades del elementoNodeList
y provocará errores si su secuencia de comandos asume que solo tiene que tratar con objetos de elementos. Además,for..in
no se garantiza la visita a las propiedades en ningún orden en particular.for...of
los bucles recorrerán correctamente los objetos NodeList.Ver también:
fuente
Esto debería funcionar, cruzar el navegador y obtener todos los nodos de "elementos".
fuente