Saya mencoba mengatur agar mendapatkan id dari semua elemen dalam sebuah HTMLCollectionOf
. Saya menulis kode berikut:
var list = document.getElementsByClassName("events");
console.log(list[0].id);
for (key in list) {
console.log(key.id);
}
Tapi saya mendapat output berikut di konsol:
event1
undefined
yang bukan itu yang saya harapkan. Mengapa output konsol kedua undefined
tetapi output konsol pertama event1
?
javascript
dom
Neuron
sumber
sumber
Array.from(document.getElementsByClassName("events")).forEach(function(item) {
Jawaban:
Menanggapi pertanyaan awal, Anda menggunakan
for/in
salah. Dalam kode Anda,key
adalah indeks. Jadi, untuk mendapatkan nilai dari pseudo-array, Anda harus melakukanlist[key]
dan mendapatkan id, Anda harus melakukannyalist[key].id
. Tapi, Anda seharusnya tidak melakukan hal inifor/in
sejak awal.Ringkasan (ditambahkan pada Des 2018)
Jangan pernah gunakan
for/in
untuk beralih ke nodeList atau HTMLCollection. Alasan untuk menghindarinya dijelaskan di bawah ini.Semua versi terbaru dari browser modern (Safari, Firefox, Chrome, Edge) semua mendukung
for/of
iterasi pada daftar DOM tersebutnodeList
atauHTMLCollection
.Ini sebuah contoh:
Untuk menyertakan browser yang lebih lama (termasuk hal-hal seperti IE), ini akan berfungsi di mana saja:
Penjelasan Untuk Mengapa Anda Tidak Harus Menggunakan
for/in
for/in
dimaksudkan untuk mengulangi properti dari suatu objek. Itu berarti ia akan mengembalikan semua properti yang dapat diubah dari suatu objek. Meskipun ini tampaknya berfungsi untuk sebuah array (mengembalikan elemen array atau elemen pseudo-array), itu juga dapat mengembalikan properti objek lain yang tidak seperti yang Anda harapkan dari elemen seperti array. Dan, coba tebak, suatuHTMLCollection
ataunodeList
objek keduanya bisa memiliki properti lain yang akan dikembalikan denganfor/in
iterasi. Saya baru saja mencoba ini di Chrome dan mengulanginya dengan cara Anda iterasi itu akan mengambil item dalam daftar (indeks 0, 1, 2, dll ...), tetapi juga akan mengambillength
danitem
properti. Thefor/in
iterasi hanya tidak akan bekerja untuk HTMLCollection.Lihat http://jsfiddle.net/jfriend00/FzZ2H/ untuk alasan Anda tidak dapat mengulangi HTMLCollection dengan
for/in
.Di Firefox,
for/in
iterasi Anda akan mengembalikan item-item ini (semua properti objek yang dapat diulang):Mudah-mudahan, sekarang Anda dapat melihat mengapa Anda ingin menggunakannya
for (var i = 0; i < list.length; i++)
sebagai gantinya sehingga Anda dapatkan0
,1
dan2
dalam iterasi Anda.Berikut di bawah ini adalah evolusi dari bagaimana browser telah berevolusi selama periode waktu 2015-2018 memberi Anda cara tambahan untuk beralih. Tidak satu pun dari ini sekarang diperlukan di browser modern karena Anda dapat menggunakan opsi yang dijelaskan di atas.
Pembaruan untuk ES6 pada tahun 2015
Ditambahkan ke ES6
Array.from()
yang akan mengubah struktur mirip array ke array yang sebenarnya. Itu memungkinkan seseorang untuk menghitung daftar secara langsung seperti ini:Demo yang berfungsi (di Firefox, Chrome, dan Edge pada April 2016): https://jsfiddle.net/jfriend00/8ar4xn2s/
Pembaruan untuk ES6 pada tahun 2016
Anda sekarang dapat menggunakan ES6 untuk / konstruksi dengan a
NodeList
danHTMLCollection
dengan hanya menambahkan ini ke kode Anda:Kemudian, Anda dapat melakukan:
Ini berfungsi di versi Chrome, Firefox, dan Edge saat ini. Ini berfungsi karena ia melampirkan iterator Array ke prototipe NodeList dan HTMLCollection sehingga ketika / untuk iterate mereka, ia menggunakan iterator Array untuk iterate mereka.
Demo kerja: http://jsfiddle.net/jfriend00/joy06u4e/ .
Pembaruan kedua untuk ES6 pada Desember 2016
Pada Desember 2016,
Symbol.iterator
dukungan telah terpasang di dalam Chrome v54 dan Firefox v50 sehingga kode di bawah ini bekerja dengan sendirinya. Itu belum built-in untuk Edge.Demo yang berfungsi (di Chrome dan Firefox): http://jsfiddle.net/jfriend00/3ddpz8sp/
Pembaruan ketiga untuk ES6 pada bulan Desember 2017
Pada Desember 2017, kemampuan ini bekerja di Edge 41.16299.15.0 untuk a
nodeList
sebagai indocument.querySelectorAll()
, tetapi bukanHTMLCollection
sebagai indocument.getElementsByClassName()
sehingga Anda harus menetapkan secara manual iterator untuk menggunakannya di Edge untuk sebuahHTMLCollection
. Ini adalah misteri total mengapa mereka memperbaiki satu jenis koleksi, tetapi tidak yang lain. Tapi, Anda setidaknya dapat menggunakan hasildocument.querySelectorAll()
denganfor/of
sintaks ES6 di versi Edge sekarang.Saya juga memperbarui jsFiddle di atas sehingga ia menguji keduanya
HTMLCollection
dannodeList
secara terpisah dan menangkap output di jsFiddle itu sendiri.Pembaruan Keempat untuk ES6 pada Maret 2018
Per mesqueeeb,
Symbol.iterator
dukungan telah built-in ke Safari juga, sehingga Anda dapat menggunakanfor (let item of list)
salah satudocument.getElementsByClassName()
ataudocument.querySelectorAll()
.Pembaruan Kelima untuk ES6 pada bulan April 2018
Rupanya, dukungan untuk iterasi
HTMLCollection
denganfor/of
akan datang ke Edge 18 pada musim gugur 2018.Pembaruan Keenam untuk ES6 pada November 2018
Saya dapat mengonfirmasi bahwa dengan Microsoft Edge v18 (yang termasuk dalam Pembaruan Windows Musim Gugur 2018), Anda sekarang dapat melakukan iterasi HTMLCollection dan NodeList dengan for / of in Edge.
Jadi, sekarang semua browser modern berisi dukungan asli untuk
for/of
iterasi dari objek HTMLCollection dan NodeList.sumber
Anda tidak dapat menggunakan
for
/in
padaNodeList
s atauHTMLCollection
s. Namun, Anda dapat menggunakan beberapaArray.prototype
metode, selama Anda.call()
mereka dan lulus dalamNodeList
atauHTMLCollection
sebagaithis
.Jadi pertimbangkan hal berikut sebagai alternatif untuk loop jfriend00
for
:Ada artikel bagus tentang MDN yang membahas teknik ini. Perhatikan peringatan mereka tentang kompatibilitas browser:
Jadi, meskipun pendekatan ini nyaman, satu
for
loop mungkin merupakan solusi yang paling kompatibel dengan browser.Pembaruan (30 Agustus 2014): Akhirnya Anda akan dapat menggunakan ES6
for
/of
!Itu sudah didukung di versi Chrome dan Firefox terbaru.
sumber
<select multiple>
. Contoh:[].map.call(multiSelect.selectedOptions, function(option) { return option.value; })
for ... of
bekerja.Di ES6, Anda bisa melakukan sesuatu seperti
[...collection]
, atauArray.from(collection)
,Misalnya:-
sumber
[...row.cells].forEach
alih - alih melakukanrow.querySelectorAll('td')
Anda dapat menambahkan dua baris ini:
HTMLCollection dikembalikan oleh getElementsByClassName dan getElementsByTagName
NodeList dikembalikan oleh querySelectorAll
Seperti ini, Anda dapat melakukan forEach:
sumber
NodeList
sudah adaforEach()
.Saya punya masalah menggunakan forEach di IE 11 dan juga Firefox 49
Saya telah menemukan solusi seperti ini
sumber
Alternatif
Array.from
adalah menggunakanArray.prototype.forEach.call
untuk setiap:
Array.prototype.forEach.call(htmlCollection, i => { console.log(i) });
peta:
Array.prototype.map.call(htmlCollection, i => { console.log(i) });
dll ...
sumber
Tidak ada alasan untuk menggunakan fitur es6 untuk menghindari
for
perulangan jika Anda menggunakan IE9 atau lebih tinggi.Dalam ES5, ada dua opsi bagus. Pertama, Anda bisa "meminjam"
Array
IniforEach
sebagai evan menyebutkan .Tetapi lebih baik lagi ...
Gunakan
Object.keys()
, yang memang memilikiforEach
dan filter untuk "memiliki properti" secara otomatis.Artinya,
Object.keys
pada dasarnya setara dengan melakukanfor... in
denganHasOwnProperty
, tetapi jauh lebih halus.sumber
Pada Maret 2016, di Chrome 49.0,
for...of
berfungsi untukHTMLCollection
:Lihat di sini dokumentasi .
Tapi itu hanya berfungsi jika Anda menerapkan solusi berikut sebelum menggunakan
for...of
:Hal yang sama diperlukan untuk digunakan
for...of
denganNodeList
:Saya percaya / berharap
for...of
akan segera bekerja tanpa solusi di atas. Masalah terbuka ada di sini:Pembaruan: Lihat komentar Expenzor di bawah ini : Ini telah diperbaiki pada April 2016. Anda tidak perlu menambahkan HTMLCollection.prototype [Symbol.iterator] = Array.prototype [Symbol.iterator]; untuk beralih melalui HTMLCollection dengan untuk ... dari
sumber
HTMLCollection.prototype[Symbol.iterator] = Array.prototype[Symbol.iterator];
untuk mengulangiHTMLCollection
denganfor...of
.Gelisah
sumber
Solusi mudah yang selalu saya gunakan
Setelah ini, Anda dapat menjalankan metode Array yang diinginkan pada seleksi
sumber
jika Anda menggunakan versi lama ES, (misalnya ES5), Anda dapat menggunakan
as any
:sumber
Anda ingin mengubahnya menjadi
sumber
for (key in list)
akan kembali beberapa properti dariHTMLCollection
yang tidak dimaksudkan untuk menjadi item dalam koleksi.