In risposta alla domanda originale, si sta utilizzando in for/in
modo errato. Nel tuo codice, key
è l'indice. Quindi, per ottenere il valore dallo pseudo-array, dovresti fare list[key]
e ottenere l'id, lo faresti list[key].id
. Ma non dovresti farlo for/in
in primo luogo.
Riepilogo (aggiunto a dicembre 2018)
Non usare mai for/in
per iterare un nodeList o un HTMLCollection. I motivi per evitarlo sono descritti di seguito.
Tutte le versioni recenti dei browser moderni (Safari, Firefox, Chrome, Edge) supportano tutte l' for/of
iterazione su elenchi DOM come nodeList
o HTMLCollection
.
Ecco un esempio:
var list = document.getElementsByClassName("events");
for (let item of list) {
console.log(item.id);
}
Per includere browser meno recenti (inclusi elementi come IE), funzionerà ovunque:
var list= document.getElementsByClassName("events");
for (var i = 0; i < list.length; i++) {
console.log(list[i].id); //second console output
}
Spiegazione del perché non si dovrebbe usare for/in
for/in
è pensato per iterare le proprietà di un oggetto. Ciò significa che restituirà tutte le proprietà iterabili di un oggetto. Mentre può sembrare funzionare per un array (restituendo elementi array o pseudo-array), può anche restituire altre proprietà dell'oggetto che non sono quelle che ti aspetti dagli elementi simili a array. E, indovina, un oggetto HTMLCollection
o nodeList
possono entrambi avere altre proprietà che verranno restituite con for/in
un'iterazione. Ho appena provato questo in Chrome e iterandolo nel modo in cui lo stavi iterando recupererà gli elementi nell'elenco (indici 0, 1, 2, ecc ...), ma recupererà anche le proprietà length
e item
. L' for/in
iterazione semplicemente non funzionerà per un HTMLCollection.
Vedi http://jsfiddle.net/jfriend00/FzZ2H/ per i motivi per cui non puoi ripetere una raccolta HTMLC for/in
.
In Firefox, la tua for/in
iterazione restituirebbe questi elementi (tutte le proprietà iterabili dell'oggetto):
0
1
2
item
namedItem
@@iterator
length
Si spera, ora si può vedere perché si desidera utilizzare for (var i = 0; i < list.length; i++)
invece così basta avere 0
, 1
e 2
nella vostra iterazione.
Di seguito è riportata un'evoluzione del modo in cui i browser si sono evoluti nel periodo 2015-2018 offrendo ulteriori modi per iterare. Nessuno di questi è ora necessario nei browser moderni poiché è possibile utilizzare le opzioni sopra descritte.
Aggiornamento per ES6 nel 2015
Aggiunto a ES6 è Array.from()
che convertirà una struttura simile ad un array in un array reale. Ciò consente di enumerare un elenco direttamente come questo:
"use strict";
Array.from(document.getElementsByClassName("events")).forEach(function(item) {
console.log(item.id);
});
Demo funzionante (in Firefox, Chrome e Edge a partire da aprile 2016): https://jsfiddle.net/jfriend00/8ar4xn2s/
Aggiornamento per ES6 nel 2016
Ora puoi usare ES6 per / of construct con a NodeList
e an HTMLCollection
semplicemente aggiungendo questo al tuo codice:
NodeList.prototype[Symbol.iterator] = Array.prototype[Symbol.iterator];
HTMLCollection.prototype[Symbol.iterator] = Array.prototype[Symbol.iterator];
Quindi, puoi fare:
var list = document.getElementsByClassName("events");
for (var item of list) {
console.log(item.id);
}
Funziona con la versione corrente di Chrome, Firefox e Edge. Questo funziona perché collega l'iteratore di array a entrambi i prototipi NodeList e HTMLCollection in modo che, quando per / di iterali, utilizza l'iteratore di array per iterarli.
Demo funzionante: http://jsfiddle.net/jfriend00/joy06u4e/ .
Secondo aggiornamento per ES6 nel dicembre 2016
A partire da dicembre 2016, il Symbol.iterator
supporto è stato integrato in Chrome v54 e Firefox v50, quindi il codice seguente funziona da solo. Non è ancora integrato per Edge.
var list = document.getElementsByClassName("events");
for (let item of list) {
console.log(item.id);
}
Demo funzionante (in Chrome e Firefox): http://jsfiddle.net/jfriend00/3ddpz8sp/
Terzo aggiornamento per ES6 nel dicembre 2017
A partire da dicembre 2017, questa funzionalità funziona in Edge 41.16299.15.0 per un nodeList
come in document.querySelectorAll()
, ma non HTMLCollection
come in, document.getElementsByClassName()
quindi è necessario assegnare manualmente l'iteratore per usarlo in Edge per un HTMLCollection
. È un mistero totale il motivo per cui avrebbero corretto un tipo di raccolta, ma non l'altro. Ma ora puoi almeno usare il risultato di document.querySelectorAll()
con la for/of
sintassi ES6 nelle versioni attuali di Edge.
Ho anche aggiornato il sopra jsFiddle in modo che controlla sia HTMLCollection
e nodeList
separatamente e cattura l'uscita nel jsFiddle stesso.
Quarto aggiornamento per ES6 a marzo 2018
Per mesqueeeb, il Symbol.iterator
supporto è stato integrato anche in Safari, quindi puoi usarlo for (let item of list)
per document.getElementsByClassName()
o document.querySelectorAll()
.
Quinto aggiornamento per ES6 nell'aprile 2018
Apparentemente, il supporto per iterare un HTMLCollection
con for/of
arriverà a Edge 18 nell'autunno 2018.
Sesto aggiornamento per ES6 nel novembre 2018
Posso confermare che con Microsoft Edge v18 (incluso in Windows Update dell'autunno 2018), è ora possibile iterare sia un HTMLCollection che un NodeList con for / of in Edge.
Quindi, ora tutti i browser moderni contengono supporto nativo per l' for/of
iterazione degli oggetti HTMLCollection e NodeList.