Eu tenho uma função Javascript que aceita uma lista de nós HTML, mas espera um array Javascript (executa alguns métodos Array nisso) e quero alimentá-lo com a saída Document.getElementsByTagName
que retorna uma lista de nós DOM.
Inicialmente pensei em usar algo simples como:
Array.prototype.slice.call(list,0)
E isso funciona bem em todos os navegadores, exceto, é claro, o Internet Explorer que retorna o erro "objeto JScript esperado", pois aparentemente a lista de nós DOM retornada por Document.getElement*
métodos não é um objeto JScript o suficiente para ser o alvo de uma chamada de função.
Advertências: não me importo de escrever código específico do Internet Explorer, mas não tenho permissão para usar nenhuma biblioteca Javascript, como JQuery, porque estou escrevendo um widget para ser incorporado em um site de terceiros e não consigo carregar bibliotecas externas que criará conflito para os clientes.
Meu último esforço é iterar a lista de nós DOM e eu mesmo criar um array, mas existe uma maneira melhor de fazer isso?
fonte
Respostas:
NodeLists são objetos de host , o uso do
Array.prototype.slice
método em objetos de host não tem garantia de funcionamento, a Especificação ECMAScript afirma:Eu recomendaria que você fizesse uma função simples para iterar
NodeList
e adicionar cada elemento existente a uma matriz:ATUALIZAR:
Como outras respostas sugerem, agora você pode usar em ambientes modernos a sintaxe de propagação ou o
Array.from
método:Mas pensando bem, acho que o caso de uso mais comum para converter um NodeList em um Array é iterar sobre ele, e agora o
NodeList.prototype
objeto tem oforEach
método nativamente , então se você estiver em um ambiente moderno, você pode usá-lo diretamente, ou ter um pollyfill.fonte
array[i] = obj[i]
vez dearray.push(obj[i])
?obj.length
algo diferente de um valor inteiro?Em es6, você pode apenas usar o seguinte:
Operador Spread
Usando
Array.from
mais referências em https://developer.mozilla.org/en-US/docs/Web/API/NodeList
fonte
Array.from()
: DArray.from
funciona, pois o TS transpila paranodelist.slice
- o que não é suportado.Array.from
spread
é usado.Usando spread (ES2015) , é tão fácil quanto:
[...document.querySelectorAll('p')]
(opcional: use Babel para transpilar o código ES6 acima para a sintaxe ES5)
Experimente no console do seu navegador e veja a mágica:
fonte
Use este truque simples
fonte
Array.prototype.slice
(ou[].slice
como você colocou)? Como observação, gostaria de comentar que o erro específico do IE que documentei no Q acontece no IE 8 ou inferior, ondemap
não está implementado de qualquer maneira. No IE 9 ("modo padrão") ou superior, ambosslice
emap
bem - sucedidos da mesma maneira.Embora não seja realmente um shim adequado, uma vez que não há especificações exigindo trabalhar com elementos DOM, fiz um para permitir que você use
slice()
desta maneira: https://gist.github.com/brettz9/6093105ATUALIZAÇÃO : quando eu levantei isso com o editor da especificação DOM4 (perguntando se eles poderiam adicionar suas próprias restrições aos objetos de host (para que a especificação exigisse que os implementadores convertessem adequadamente esses objetos quando usados com métodos de array) além da especificação ECMAScript que tinha permitido para a independência de implementação), ele respondeu que "Objetos de host são mais ou menos obsoletos por ES6 / IDL." Vejo por http://www.w3.org/TR/WebIDL/#es-array que as especificações podem usar este IDL para definir "objetos de matriz de plataforma", mas http://www.w3.org/TR/domcore/ não parece estar usando o novo IDL para
HTMLCollection
(embora pareça que pode estarElement.attributes
usando, embora apenas afirme explicitamente que está usando WebIDL para DOMString e DOMTimeStamp). vejo sim[ArrayClass]
(que herda de Array.prototype) é usado paraNodeList
(eNamedNodeMap
agora está obsoleto em favor do único item que ainda o estaria usandoElement.attributes
). Em qualquer caso, parece que se tornará um padrão. O ES6Array.from
também pode ser mais conveniente para tais conversões do que ter que especificarArray.prototype.slice
e mais claro do que semanticamente[].slice()
(e a forma mais curta,Array.slice()
(um "array genérico"), até onde eu sei, não se tornou um comportamento padrão).fonte
Hoje, em 2018, poderíamos usar o ECMAScript 2015 (6ª edição) ou ES6, mas nem todos os navegadores conseguem entendê-lo (por exemplo, o IE não entende tudo). Se você quiser, pode usar o ES6 da seguinte maneira:
var array = [... NodeList];
( como operador de spread ) ouvar array = Array.from(NodeList);
.Em outro caso (se você não pode usar ES6), você pode usar o caminho mais curto para converter um
NodeList
emArray
:var array = [].slice.call(NodeList, 0);
.Por exemplo:
Mas se você deseja iterar
DOM
facilmente na lista de nós, não é necessário converter aNodeList
em umArray
. É possível fazer um loop sobre os itens em umNodeList
usando:Não fique tentado a usar
for...in
oufor each...in
enumerar os itens da lista, pois isso também enumerará o comprimento e as propriedades do item doNodeList
e causará erros se o seu script assumir que ele só precisa lidar com objetos de elemento. Além disso,for..in
não é garantido visitar as propriedades em qualquer ordem específica.for...of
os loops farão um loop nos objetos NodeList corretamente.Veja também:
fonte
Isso deve funcionar, cruzar o navegador e obter todos os nós de "elemento".
fonte