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.getElementsByTagNameque 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.sliceno 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
NodeListy 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.frommé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.prototypeobjeto tiene elforEachmé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.lengthcualquier otra cosa que no sea un valor entero?En es6 puede usar lo siguiente:
Operador de propagación
Utilizando
Array.frommás referencias en https://developer.mozilla.org/en-US/docs/Web/API/NodeList
fuente
Array.from(): DArray.fromfunciona, ya que TS transpila esto anodelist.slice, lo cual no es compatible.Array.fromspreadse 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[].slicecomo 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, dondemapno está implementado de todos modos. En IE 9 ("modo estándar") o superior, ambossliceymaptienen é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.attributesporque solo indica explícitamente que está usando WebIDL para DOMString y DOMTimeStamp). Yo veo[ArrayClass](que hereda de Array.prototype) se usa paraNodeList(yNamedNodeMapahora 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.fromtambién podría ser más conveniente para tales conversiones que tener que especificarArray.prototype.slicey 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
NodeListen unArray:var array = [].slice.call(NodeList, 0);.Por ejemplo:
Pero si solo desea iterar sobre la
DOMlista de nodos de manera fácil, entonces no necesita convertirNodeLista enArray. Es posible recorrer los elementos en unNodeListuso:No se sienta tentado a utilizar
for...inofor each...inenumerar los elementos de la lista, ya que eso también enumerará la longitud y las propiedades del elementoNodeListy provocará errores si su secuencia de comandos asume que solo tiene que tratar con objetos de elementos. Además,for..inno se garantiza la visita a las propiedades en ningún orden en particular.for...oflos 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