Estou tentando definir get id de todos os elementos em um HTMLCollectionOf
. Eu escrevi o seguinte código:
var list = document.getElementsByClassName("events");
console.log(list[0].id);
for (key in list) {
console.log(key.id);
}
Mas eu consegui a seguinte saída no console:
event1
undefined
o que não é o que eu esperava. Por que a segunda saída undefined
do console é a primeira saída do console event1
?
javascript
dom
Neuron
fonte
fonte
Array.from(document.getElementsByClassName("events")).forEach(function(item) {
Respostas:
Em resposta à pergunta original, você está usando
for/in
incorretamente. No seu código,key
é o índice. Portanto, para obter o valor da pseudo-matriz, você teria que fazerlist[key]
e obter o ID, você farialist[key].id
. Mas você não deve fazer issofor/in
em primeiro lugar.Resumo (adicionado em dezembro de 2018)
Nunca use
for/in
para iterar um nodeList ou um HTMLCollection. Os motivos para evitá-lo estão descritos abaixo.Todas as versões recentes de navegadores modernos (Safari, Firefox, Chrome, Edge) todo o apoio
for/of
iteração no DOM lista taisnodeList
ouHTMLCollection
.Aqui está um exemplo:
Para incluir navegadores mais antigos (incluindo coisas como o IE), isso funcionará em qualquer lugar:
Explicação sobre por que você não deve usar
for/in
for/in
destina-se a iterar as propriedades de um objeto. Isso significa que ele retornará todas as propriedades iteráveis de um objeto. Embora pareça funcionar para uma matriz (retornando elementos da matriz ou elementos de pseudo-matriz), também pode retornar outras propriedades do objeto que não são o que você espera dos elementos semelhantes à matriz. E, adivinhe, um objetoHTMLCollection
ounodeList
pode ter outras propriedades que serão retornadas com umafor/in
iteração. Eu apenas tentei isso no Chrome e a iteração da maneira que você estava iterando recuperará os itens da lista (índices 0, 1, 2, etc ...), mas também recuperará as propriedadeslength
eitem
. Afor/in
iteração simplesmente não funcionará para uma HTMLCollection.Veja http://jsfiddle.net/jfriend00/FzZ2H/ para saber por que você não pode iterar uma HTMLCollection
for/in
.No Firefox, sua
for/in
iteração retornaria esses itens (todas as propriedades iteráveis do objeto):Felizmente, agora você pode ver por que você deseja usar
for (var i = 0; i < list.length; i++)
em vez de modo que você acabou de começar0
,1
e2
em sua iteração.A seguir, é apresentada uma evolução de como os navegadores evoluíram ao longo do período 2015-2018, oferecendo maneiras adicionais de iterar. Agora nada disso é necessário em navegadores modernos, pois você pode usar as opções descritas acima.
Atualização para ES6 em 2015
Adicionado ao ES6 é
Array.from()
que ele converterá uma estrutura semelhante a uma matriz em uma matriz real. Isso permite enumerar uma lista diretamente assim:Demonstração de trabalho (no Firefox, Chrome e Edge em abril de 2016): https://jsfiddle.net/jfriend00/8ar4xn2s/
Atualização para ES6 em 2016
Agora você pode usar o ES6 para / de construção com um
NodeList
e umHTMLCollection
por apenas adicionando isso ao seu código:Então, você pode fazer:
Isso funciona na versão atual do Chrome, Firefox e Edge. Isso funciona porque anexa o iterador Array aos protótipos NodeList e HTMLCollection, para que, quando for iterado por / deles, use o iterador Array para iterá-los.
Demonstração de trabalho: http://jsfiddle.net/jfriend00/joy06u4e/ .
Segunda atualização do ES6 em dezembro de 2016
Desde dezembro de 2016, o
Symbol.iterator
suporte foi incorporado ao Chrome v54 e Firefox v50, portanto, o código abaixo funciona por si só. Ainda não está embutido no Edge.Demonstração de trabalho (no Chrome e Firefox): http://jsfiddle.net/jfriend00/3ddpz8sp/
Terceira atualização para ES6 em dezembro de 2017
A partir de dezembro de 2017, esse recurso funcionaria no Edge 41.16299.15.0 para a
nodeList
como emdocument.querySelectorAll()
, mas não paraHTMLCollection
como,document.getElementsByClassName()
portanto, você deve atribuir manualmente o iterador para usá-lo no Edge para umHTMLCollection
. É um mistério total o motivo pelo qual eles consertam um tipo de coleção, mas não o outro. Porém, você pode pelo menos usar o resultado da sintaxedocument.querySelectorAll()
ES6for/of
nas versões atuais do Edge agora.Também atualizei o jsFiddle acima para que ele teste ambos
HTMLCollection
enodeList
separadamente e capture a saída no próprio jsFiddle.Quarta atualização do ES6 em março de 2018
Por mesqueeeb, o
Symbol.iterator
suporte também foi incorporado ao Safari, para que você possa usarfor (let item of list)
umdocument.getElementsByClassName()
ou outrodocument.querySelectorAll()
.Quinta atualização para ES6 em abril de 2018
Aparentemente, o suporte para iterar um
HTMLCollection
comfor/of
chegará ao Edge 18 no outono de 2018.Sexta atualização para ES6 em novembro de 2018
Posso confirmar que, com o Microsoft Edge v18 (incluído no Windows Update de outono de 2018), agora você pode iterar um HTMLCollection e um NodeList com for / of no Edge.
Portanto, agora todos os navegadores modernos contêm suporte nativo para
for/of
iteração dos objetos HTMLCollection e NodeList.fonte
Você não pode usar
for
/in
onNodeList
s ouHTMLCollection
s. No entanto, você pode usar algunsArray.prototype
métodos, desde que você.call()
os use e passe noNodeList
ouHTMLCollection
comothis
.Portanto, considere o seguinte como uma alternativa ao loop de jfriend00
for
:Há um bom artigo sobre o MDN que aborda essa técnica. Observe o aviso sobre a compatibilidade do navegador:
Portanto, embora essa abordagem seja conveniente, um
for
loop pode ser a solução mais compatível com o navegador.Atualização (30 de agosto de 2014): Eventualmente, você poderá usar o ES6
for
/of
!Já é suportado em versões recentes do Chrome e Firefox.
fonte
<select multiple>
. Exemplo:[].map.call(multiSelect.selectedOptions, function(option) { return option.value; })
for ... of
funciona.No ES6, você poderia fazer algo como
[...collection]
, ouArray.from(collection)
,Por exemplo:-
fonte
[...row.cells].forEach
vez de fazer umrow.querySelectorAll('td')
você pode adicionar estas duas linhas:
HTMLCollection é retornado por getElementsByClassName e getElementsByTagName
NodeList é retornado por querySelectorAll
Assim você pode fazer um forEach:
fonte
NodeList
já possuiforEach()
.Ocorreu um problema ao usar o forEach no IE 11 e também o Firefox 49
Eu encontrei uma solução alternativa como esta
fonte
Alternativa para
Array.from
é usarArray.prototype.forEach.call
para cada:
Array.prototype.forEach.call(htmlCollection, i => { console.log(i) });
mapa:
Array.prototype.map.call(htmlCollection, i => { console.log(i) });
ect ...
fonte
Não há razão para usar os recursos es6 para escapar do
for
loop se você estiver no IE9 ou superior.No ES5, existem duas boas opções. Primeiro, você pode "emprestar"
Array
éforEach
como evan menciona .Mas melhor ainda ...
Use
Object.keys()
, que não têmforEach
e filtros para "próprias propriedades" automaticamente.Ou seja,
Object.keys
é essencialmente equivalente a fazer afor... in
com aHasOwnProperty
, mas é muito mais suave.fonte
Em março de 2016, no Chrome 49.0,
for...of
trabalha paraHTMLCollection
:Veja aqui a documentação .
Mas isso só funciona se você aplicar a seguinte solução alternativa antes de usar o
for...of
:O mesmo é necessário para usar
for...of
comNodeList
:Acredito / espero
for...of
que funcione em breve sem a solução alternativa acima. A questão em aberto está aqui:Atualização: Veja o comentário do Expenzor abaixo: Isso foi corrigido em abril de 2016. Você não precisa adicionar HTMLCollection.prototype [Symbol.iterator] = Array.prototype [Symbol.iterator]; para iterar sobre uma HTMLCollection com for ... of
fonte
HTMLCollection.prototype[Symbol.iterator] = Array.prototype[Symbol.iterator];
para iterar ao longo de umHTMLCollection
comfor...of
.No limite
fonte
Solução fácil que eu sempre uso
Depois disso, você pode executar qualquer método de matriz desejado na seleção
fonte
se você usar versões mais antigas do ES (ES5, por exemplo), poderá usar
as any
:fonte
Você deseja alterá-lo para
fonte
for (key in list)
retornará várias propriedades doHTMLCollection
que não devem ser itens na coleção.