Próbuję ustawić get id wszystkich elementów w pliku HTMLCollectionOf
. Napisałem następujący kod:
var list = document.getElementsByClassName("events");
console.log(list[0].id);
for (key in list) {
console.log(key.id);
}
Ale dostałem następujące dane wyjściowe w konsoli:
event1
undefined
czego się nie spodziewałem. Dlaczego jest to wyjście drugiej konsoli, undefined
ale pierwsze wyjście konsoli event1
?
javascript
dom
Neuron
źródło
źródło
Array.from(document.getElementsByClassName("events")).forEach(function(item) {
Odpowiedzi:
W odpowiedzi na oryginalne pytanie używasz
for/in
nieprawidłowo. W twoim kodziekey
jest indeks. Tak więc, aby uzyskać wartość z pseudo-tablicy, musiałbyś to zrobić,list[key]
a żeby uzyskać identyfikator, zrobiłbyś tolist[key].id
. Alefor/in
przede wszystkim nie powinieneś tego robić .Podsumowanie (dodano w grudniu 2018 r.)
Nigdy nie używaj
for/in
do iteracji nodeList lub HTMLCollection. Powody, dla których można tego uniknąć, opisano poniżej.Wszystkie najnowsze wersje nowoczesnych przeglądarek (Safari, Firefox, Chrome, Krawędź) wszelkie wsparcie
for/of
iteracja na DOM wymienia takienodeList
lubHTMLCollection
.Oto przykład:
Aby uwzględnić starsze przeglądarki (w tym takie jak IE), będzie to działać wszędzie:
Wyjaśnienie, dlaczego nie powinieneś używać
for/in
for/in
służy do iteracji właściwości obiektu. Oznacza to, że zwróci wszystkie iterowalne właściwości obiektu. Chociaż może się wydawać, że działa dla tablicy (zwraca elementy tablicy lub elementy pseudo-tablicy), może również zwracać inne właściwości obiektu, które nie są tym, czego oczekujesz od elementów podobnych do tablicy. I zgadnij, co,HTMLCollection
albonodeList
obiekt może mieć inne właściwości, które zostaną zwrócone zfor/in
iteracją. Właśnie próbowałem tego w Chrome i iteracja w taki sposób, w jaki iterowałeś, pobierze elementy z listy (indeksy 0, 1, 2 itd.), Ale także pobierze właściwościlength
iitem
.for/in
Iteracja po prostu nie będzie działać na HTMLCollection.Zobacz http://jsfiddle.net/jfriend00/FzZ2H/, aby dowiedzieć się, dlaczego nie możesz iterować kolekcji HTMLCollection
for/in
.W przeglądarce Firefox twoja
for/in
iteracja zwróciłaby te elementy (wszystkie iterowalne właściwości obiektu):Mam nadzieję, że teraz można zobaczyć, dlaczego chcesz używać
for (var i = 0; i < list.length; i++)
zamiast tak po prostu dostać0
,1
a2
w iteracji.Poniżej znajduje się ewolucja ewolucji przeglądarek w okresie 2015-2018, co daje dodatkowe możliwości iteracji. Żadne z nich nie są teraz potrzebne w nowoczesnych przeglądarkach, ponieważ możesz skorzystać z opcji opisanych powyżej.
Aktualizacja dla ES6 w 2015 roku
Dodano do ES6 to,
Array.from()
że konwertuje strukturę podobną do tablicy na rzeczywistą tablicę. To pozwala wyliczyć listę bezpośrednio w ten sposób:Działające demo (w Firefox, Chrome i Edge od kwietnia 2016 r.): Https://jsfiddle.net/jfriend00/8ar4xn2s/
Aktualizacja dla ES6 w 2016 roku
Możesz teraz używać ES6 dla / z konstruktem za pomocą a
NodeList
iHTMLCollection
po prostu dodając to do swojego kodu:Następnie możesz wykonać:
Działa to w bieżącej wersji Chrome, Firefox i Edge. Działa to, ponieważ dołącza iterator Array zarówno do prototypów NodeList, jak i HTMLCollection, dzięki czemu podczas ich iteracji używa iteratora Array do iteracji.
Działające demo: http://jsfiddle.net/jfriend00/joy06u4e/ .
Druga aktualizacja ES6 w grudniu 2016 r
Od grudnia 2016 r.
Symbol.iterator
Obsługa Chrome jest wbudowana w Chrome v54 i Firefox v50, więc poniższy kod działa sam. Nie jest jeszcze wbudowany w Edge.Działające demo (w Chrome i Firefox): http://jsfiddle.net/jfriend00/3ddpz8sp/
Trzecia aktualizacja ES6 w grudniu 2017 r
Od grudnia 2017 r. Ta funkcja działa w Edge 41.16299.15.0 dla wersji
nodeList
asdocument.querySelectorAll()
, ale nie dla wersjiHTMLCollection
as,document.getElementsByClassName()
więc musisz ręcznie przypisać iterator do użycia w Edge dla wersjiHTMLCollection
. Jest całkowitą tajemnicą, dlaczego naprawili jeden typ kolekcji, ale nie drugi. Ale teraz możesz przynajmniej użyć wynikudocument.querySelectorAll()
zefor/of
składnią ES6 w bieżących wersjach Edge.Ja również zaktualizowane wyżej jsFiddle więc testuje zarówno
HTMLCollection
inodeList
osobno i oddaje moc w samej jsFiddle.Czwarta aktualizacja ES6 w marcu 2018 r
W przypadku mesqueeeb
Symbol.iterator
obsługa Safari została również wbudowana, dzięki czemu można korzystaćfor (let item of list)
z jednegodocument.getElementsByClassName()
lub drugiegodocument.querySelectorAll()
.Piąta aktualizacja ES6 w kwietniu 2018 r
Najwyraźniej wsparcie dla iteracji
HTMLCollection
zfor/of
pojawi się na Edge 18 jesienią 2018 r.Szósta aktualizacja ES6 w listopadzie 2018 r
Mogę potwierdzić, że dzięki Microsoft Edge v18 (który jest zawarty w Windows Update Fall 2018), możesz teraz iterować zarówno HTMLCollection, jak i NodeList z for / of w Edge.
Tak więc teraz wszystkie nowoczesne przeglądarki zawierają natywną obsługę
for/of
iteracji zarówno obiektów HTMLCollection, jak i NodeList.źródło
Nie możesz używać
for
/in
onNodeList
s lubHTMLCollection
s. Możesz jednak użyć niektórychArray.prototype
metod, o ile.call()
je zastosujesz i przekazać wNodeList
lubHTMLCollection
asthis
.Zastanów się
for
zatem, czy nie jest to alternatywa dla pętli jfriend00 :Istnieje dobry artykuł na temat MDN, który dotyczy tej techniki. Zwróć jednak uwagę na ich ostrzeżenie dotyczące zgodności przeglądarki:
Chociaż takie podejście jest wygodne,
for
pętla może być najbardziej kompatybilnym rozwiązaniem dla przeglądarki.Aktualizacja (30 sierpnia 2014 r.): W końcu będziesz mógł używać ES6
for
/of
!Jest już obsługiwany w najnowszych wersjach Chrome i Firefox.
źródło
<select multiple>
. Przykład:[].map.call(multiSelect.selectedOptions, function(option) { return option.value; })
for ... of
działa.W ES6, można zrobić coś takiego
[...collection]
, lubArray.from(collection)
,Na przykład:-
źródło
[...row.cells].forEach
zamiast robićrow.querySelectorAll('td')
możesz dodać te dwie linie:
HTMLCollection jest zwracany przez getElementsByClassName i getElementsByTagName
NodeList jest zwracany przez querySelectorAll
W ten sposób możesz zrobić forEach:
źródło
NodeList
już maforEach()
.Miałem problem z korzystaniem z forEach w IE 11, a także Firefox 49
Znalazłem takie obejście
źródło
Alternatywą
Array.from
jest użycieArray.prototype.forEach.call
dla każdego:
Array.prototype.forEach.call(htmlCollection, i => { console.log(i) });
mapa:
Array.prototype.map.call(htmlCollection, i => { console.log(i) });
ect ...
źródło
Nie ma powodu, aby używać funkcji es6, aby uniknąć
for
pętli, jeśli korzystasz z IE9 lub nowszej wersji.W ES5 są dwie dobre opcje. Po pierwsze, możesz „pożyczyć”
Array
,forEach
jak wspomina Evan .Ale jeszcze lepiej ...
Stosowanie
Object.keys()
, które nie mająforEach
i filtry do „własnych” Automatycznie właściwości.Oznacza to, że
Object.keys
jest zasadniczo równoważne z robieniemfor... in
zHasOwnProperty
, ale jest znacznie płynniejsze.źródło
Od marca 2016 r. W przeglądarce Chrome 49.0
for...of
działaHTMLCollection
:Zobacz tutaj dokumentację .
Ale działa to tylko wtedy, gdy zastosujesz następujące obejście przed użyciem
for...of
:To samo jest konieczne do korzystania
for...of
zNodeList
:Wierzę / mam nadzieję,
for...of
że wkrótce zadziała bez powyższego obejścia. Otwarty problem jest tutaj:Aktualizacja: patrz komentarz Expenzora poniżej: Zostało to naprawione w kwietniu 2016 r. Nie trzeba dodawać HTMLCollection.prototype [Symbol.iterator] = Array.prototype [Symbol.iterator]; iterować przez HTMLCollection z dla ... z
źródło
HTMLCollection.prototype[Symbol.iterator] = Array.prototype[Symbol.iterator];
do iteracji w ciąguHTMLCollection
zfor...of
.Na krawędzi
źródło
Proste obejście, którego zawsze używam
Następnie możesz uruchomić dowolne pożądane metody Array dla zaznaczenia
źródło
jeśli używasz starszych wersji ES (na przykład ES5), możesz użyć
as any
:źródło
Chcesz to zmienić na
źródło
for (key in list)
Powróci kilka właściwościHTMLCollection
, które nie mają być elementy w kolekcji.