Saya menggunakan JSLint pada file JavaScript milik saya. Itu melemparkan kesalahan:
for( ind in evtListeners ) {
Masalah pada baris 41 karakter 9: Tubuh for in harus dibungkus dengan pernyataan if untuk menyaring properti yang tidak diinginkan dari prototipe.
Apa artinya ini?
javascript
jslint
jrharshath
sumber
sumber
if (evtListeners.hasOwnProperty(ind))
untuk membatasi pemrosesan hanya untuk memiliki properti (tidak diwariskan). Namun, dalam beberapa kasus Anda benar-benar ingin mengulang semua properti, termasuk yang diwarisi. Dalam hal itu, JSLint memaksa Anda untuk membungkus loop body dalam pernyataan if untuk memutuskan properti mana yang benar-benar Anda inginkan. Ini akan berhasil dan membuat JSlint senang:if (evtListeners[ind] !== undefined)
Jawaban:
Pertama-tama, jangan pernah menggunakan
for in
loop untuk menghitung lebih dari satu array. Tidak pernah. Pakai tua yang bagusfor(var i = 0; i<arr.length; i++)
.Alasan di balik ini adalah sebagai berikut: setiap objek dalam JavaScript memiliki bidang khusus yang disebut
prototype
. Segala sesuatu yang Anda tambahkan ke bidang itu akan dapat diakses pada setiap objek jenis itu. Misalkan Anda ingin semua array memiliki fungsi baru yang keren yang disebutfilter_0
yang akan menyaring nol.Ini adalah cara standar untuk memperluas objek dan menambahkan metode baru. Banyak perpustakaan melakukan ini. Namun, mari kita lihat cara
for in
kerjanya sekarang:Apakah kamu lihat? Tiba-tiba berpikir filter_0 adalah indeks array lain. Tentu saja, ini bukan benar-benar indeks numerik, tetapi
for in
menghitung melalui bidang objek, bukan hanya indeks numerik. Jadi kita sekarang menghitung melalui setiap indeks numerik danfilter_0
. Tetapifilter_0
bukan bidang objek array tertentu, setiap objek array memiliki properti ini sekarang.Untungnya, semua objek memiliki
hasOwnProperty
metode, yang memeriksa apakah bidang ini benar-benar milik objek itu sendiri atau jika itu hanya diwarisi dari rantai prototipe dan dengan demikian milik semua objek jenis itu.Perhatikan, bahwa meskipun kode ini berfungsi seperti yang diharapkan untuk array, Anda tidak boleh, tidak pernah , menggunakan
for in
danfor each in
untuk array. Ingat bahwafor in
menghitung bidang objek, bukan indeks array atau nilai.sumber
for in
untuk mengulangi array karena bahasa tidak akan mengurutkan urutan yangfor in
akan disebutkan lebih dari satu array. Mungkin tidak dalam urutan angka. Selain itu, jika Anda menggunakan konstruksi gaya `for (i = 0; i <array.length; i ++), Anda dapat yakin bahwa Anda hanya mengulangi indeks numerik secara berurutan, dan tidak ada properti alfanumerik.for-in
lingkaran (yang luar biasa, omong-omong), kita harus mendidik mereka bagaimana mereka bekerja (dilakukan dengan benar dalam jawaban ini) dan memperkenalkan merekaObject.defineProperty()
sehingga mereka dapat dengan aman memperpanjang prototipe mereka tanpa merusak apa pun. Kebetulan, memperluas prototipe objek asli tidak boleh dilakukan tanpaObject.defineProperty
.Douglas Crockford, penulis jslint telah menulis (dan berbicara) tentang masalah ini berkali-kali. Ada bagian pada ini halaman situs Web-nya yang meliputi ini:
Crockford juga memiliki seri video tentang teater YUI di mana ia berbicara tentang ini. Seri video / pembicaraan Crockford tentang javascript harus dilihat jika Anda sedikit serius tentang javascript.
sumber
Buruk: (jsHint akan melempar kesalahan)
Baik:
sumber
Jawaban Vava ada di sasaran. Jika Anda menggunakan jQuery, maka
$.each()
fungsinya menangani ini, maka itu lebih aman untuk digunakan.sumber
$.each
(atau underscore.js_.each
) jika Anda bisa lolos denganfor
loop mentah . jsperf memiliki beberapa tes perbandingan yang membuka mata yang layak dijalankan.@semua - semua yang ada di JavaScript adalah objek (), jadi pernyataan seperti "hanya gunakan ini pada objek" agak menyesatkan. Selain itu, JavaScript tidak diketik dengan kuat sehingga 1 == "1" benar (walaupun 1 === "1" tidak, Crockford besar dalam hal ini). Ketika datang ke konsep array progromatik di JS, mengetik penting dalam definisi.
@Brenton - Tidak perlu menjadi diktator terminologi; "array asosiatif", "kamus", "hash", "objek", semua konsep pemrograman ini berlaku untuk satu struktur di JS. Ini adalah pasangan nilai nama (kunci, indeks), di mana nilainya dapat berupa objek lain (string juga objek)
Jadi,
new Array()
sama dengan[]
new Object()
kira-kira mirip dengan{}
Membuat struktur yang merupakan array dengan batasan bahwa semua indeks (alias kunci) harus berupa bilangan bulat. Ini juga memungkinkan untuk penetapan otomatis indeks baru melalui .push ()
Memang paling baik ditangani via
for(initialization;condition;update){
Tapi bagaimana dengan:
Coba ini:
Mungkin bukan penggunaan array yang terbaik, tetapi hanya sebuah ilustrasi yang tidak selalu jelas.
Jika Anda tahu kunci Anda, dan pasti jika itu bukan bilangan bulat, satu-satunya pilihan struktur seperti array adalah objek.
sumber
Tentunya agak ekstrem untuk dikatakan
?
Layak menyoroti bagian dalam ekstrak Douglas Crockford
Jika Anda memerlukan array asosiatif (alias hashtable / kamus) di mana kunci dinamai bukannya diindeks secara numerik, Anda harus mengimplementasikan ini sebagai objek, misalnya
var myAssocArray = {key1: "value1", key2: "value2"...};
.Dalam hal ini
myAssocArray.length
akan muncul nol (karena objek ini tidak memiliki properti 'panjang'), dan Andai < myAssocArray.length
tidak akan membuat Anda terlalu jauh. Selain memberikan kenyamanan yang lebih besar, saya berharap array asosiatif untuk menawarkan keunggulan kinerja dalam banyak situasi, karena kunci array dapat menjadi properti yang berguna (yaitu properti ID atau nama anggota array), yang berarti Anda tidak perlu beralih melalui yang panjang. array berulang kali mengevaluasi apakah pernyataan untuk menemukan entri array yang Anda cari.Bagaimanapun, terima kasih juga untuk penjelasan dari pesan kesalahan JSLint, saya akan menggunakan cek 'isOwnProperty' sekarang ketika berinteraksi melalui berbagai array asosiatif saya!
sumber
length
properti, tetapi Anda dapat melakukannya dengan cara lain:var myArr = []; myArr['key1'] = 'hello'; myArr['key2'] = 'world';
var myArr = []
, itu harusvar myArr = {}
dalam PHP mereka adalah hal yang sama, tetapi tidak di JS.Ini berarti Anda harus memfilter properti evtListeners dengan metode hasOwnProperty .
sumber
Hanya untuk menambahkan pada topik untuk di / untuk / $ masing-masing, saya menambahkan kasus uji jsperf untuk menggunakan $ .each vs untuk di: http://jsperf.com/each-vs-for-in/2
Browser / versi yang berbeda menanganinya secara berbeda, tetapi tampaknya $ .each dan langsung masuk adalah pilihan termurah untuk performa.
Jika Anda menggunakannya untuk beralih melalui array / objek asosiatif, mengetahui apa yang Anda cari dan mengabaikan semua yang lain, gunakan $ .each jika Anda menggunakan jQuery, atau hanya untuk di (dan kemudian istirahat; begitu Anda sudah mencapai apa yang Anda tahu harus menjadi elemen terakhir)
Jika Anda mengulangi melalui array untuk melakukan sesuatu dengan setiap pasangan kunci di dalamnya, harus menggunakan metode hasOwnProperty jika Anda TIDAK menggunakan jQuery, dan menggunakan $ .each jika Anda DO menggunakan jQuery.
Selalu gunakan
for(i=0;i<o.length;i++)
jika Anda tidak memerlukan array asosiatif ... lol chrome melakukan itu 97% lebih cepat dari pada untuk atau$.each
sumber