Untuk setiap array di javascript?

Bagaimana saya bisa melihat semua entri dalam array menggunakan javascript?

Saya pikir itu kira-kira seperti ini:

 forEach(instance in theArray) 

Di mana theArray adalah array saya, tetapi tampaknya salah.

4041
17 февр. Dante1986 ditetapkan pada 17 Februari 2012-02-17 16:51 '12 pada pukul 16:51 2012-02-17 16:51
@ 32 jawaban
  • 1
  • 2

Tl; DR

  • Jangan gunakan for-in jika Anda tidak menggunakannya dengan perlindungan atau, setidaknya, tidak tahu mengapa itu bisa menggigit Anda.
  • Taruhan terbaik Anda biasanya

    • for-of loop (hanya untuk ES2015 +),
    • Array#forEach ( spec | MDN ) (atau sanak saudaranya some dan semacamnya) (hanya ES5 +)
    • sederhana kuno for loop,
    • atau input masuk dengan perlindungan.

Tetapi masih banyak yang harus dijelajahi, baca terus ...


JavaScript memiliki semantik yang kuat untuk mengubah array dan objek tipe array secara siklikal. Saya membagi jawaban menjadi dua bagian: opsi untuk array otentik dan opsi untuk hal-hal yang hanya mirip dengan array, seperti objek arguments , objek iterable lainnya (ES2015 +), koleksi DOM, dll.

Saya segera menyadari bahwa sekarang Anda dapat menggunakan opsi ES2015, bahkan pada mesin ES5, dengan mengirim ES2015 ke ES5. Temukan "ES2015 transpiling" / "ES6 transpiling" untuk lebih ...

Nah, lihat opsi kami:

Untuk array nyata

Anda memiliki tiga opsi dalam ECMAScript 5 ("ES5"), versi yang paling banyak didukung saat ini, dan dua lagi ditambahkan dalam ECMAScript 2015 ("ES2015", "ES6"):

  1. Gunakan forEach dan terkait (ES5 +)
  2. Gunakan simpel for loop
  3. Gunakan dengan benar for-in
  4. Gunakan for-of (gunakan implisit iterator) (ES2015 +)
  5. Gunakan iterator secara eksplisit (ES2015 +)

Detail:

1. Gunakan forEach dan terkait

Di lingkungan modern tanpa batas (well, bukan di IE8), di mana Anda memiliki akses ke fungsi Array ditambahkan oleh ES5 (secara >forEach ( spec | MDN ):

 var a = ["a", "b", "c"]; a.forEach(function(entry) { console.log(entry); }); 

forEach menerima fungsi panggilan balik dan, secara opsional, nilai yang digunakan seperti this saat memanggil panggilan balik ini (tidak digunakan di atas). Callback dipanggil untuk setiap entri dalam array untuk melewati entri yang tidak ada dalam array jarang. Meskipun saya hanya menggunakan satu argumen di atas, callback dipanggil dengan tiga: nilai setiap record, indeks dari record ini, dan tautan ke array yang Anda u>

Jika Anda tidak mendukung browser lawas, seperti IE8 (yang NetApps tunjukkan di lebih dari 4% pasar pada saat penulisan ini pada bulan September 2016), Anda dapat dengan senang hati menggunakan forEach di halaman web universal tanpa tata letak halaman. Jika Anda perlu mendukung browser lawas, mudah untuk melakukan operasi shimming / polyfilling forEach (cari "es5 shim" untuk beberapa opsi).

forEach memiliki keuntungan bahwa Anda tidak perlu mendeklarasikan nilai pengindeksan dan variabel di area konten, karena mereka disediakan sebagai argumen untuk fungsi iterasi dan sangat berorientasi pada iterasi ini.

Jika Anda khawatir tentang waktu yang diperlukan untuk menjalankan panggilan fungsi untuk setiap rekaman array, jangan; detail

Selain itu, forEach adalah fungsi "loop through them all", tetapi ES5 telah mendefinisikan beberapa "elaborasi melalui fungsi array dan hal" yang berguna lainnya, termasuk:

  • every (menghentikan loop saat pertama kali callback mengembalikan false atau sesuatu yang salah)
  • some (menghentikan loop saat pertama kali callback mengembalikan true atau sesuatu yang masuk akal)
  • filter (membuat array baru yang menyertakan elemen di mana fungsi filter mengembalikan true dan menghi>false )
  • map (membuat larik baru nilai pengembalian balik)
  • reduce (menambah nilai, memanggil kembali callback, melewati nilai sebelumnya, melihat spesifikasi untuk detail, berguna untuk menjumlahkan isi array dan banyak hal lainnya)
  • reduceRight (misalnya, reduce , tetapi bekerja dalam urutan menurun, bukan dalam urutan menaik)

2. Gunakan simpel for loop

Terkadang cara lama yang terbaik:

 var index; var a = ["a", "b", "c"]; for (index = 0; index < a.length; ++index) { console.log(a[index]); } 

Jika panjang array tidak berubah selama siklus, dan kinerjanya adalah kode sensitif (tidak mungkin), versi tangkapan yang sedikit lebih rumit dengan panjang depan bisa sedikit lebih cepat:

 var index, len; var a = ["a", "b", "c"]; for (index = 0, len = a.length; index < len; ++index) { console.log(a[index]); } 

Dan / atau menghitung kembali:

 var index; var a = ["a", "b", "c"]; for (index = a.length - 1; index >= 0; --index) { console.log(a[index]); } 

Tetapi dengan mekanisme JavaScript modern, Anda jarang harus menggali jus terakhir ini.

Di ES2015 dan lebih tinggi, Anda bisa membuat indeks dan variabel nilai lokal for for loop:

 let a = ["a", "b", "c"]; for (let index = 0; index < a.length; ++index) { let value = a[index]; } //console.log(index); // Would cause "ReferenceError: index is not defined" //console.log(value); // Would cause "ReferenceError: value is not defined" 

Dan ketika Anda melakukan ini, tidak hanya value tetapi juga index diciptakan kembali untuk setiap iterasi dari loop, yaitu, penutupan yang dibuat dalam tag loop berisi referensi ke index (dan value ) yang dibuat untuk iterasi khusus ini:

 let divs = document.querySelectorAll("div"); for (let index = 0; index < divs.length; ++index) { divs[index].addEventListener('click', e => { alert("Index is: " + index); }); } 

Jika Anda memiliki lima div, Anda akan mendapatkan "Index is: 0", jika Anda mengklik yang pertama dan "Index is: 4", jika Anda mengklik yang terakhir. Ini tidak berfungsi jika Anda menggunakan var daripada let .

3. Gunakan for-in dengan benar.

Anda akan membuat orang-orang mengatakan kepada Anda untuk menggunakan for-in , tetapi ini bukan for-in apa for-in . for-in ditulis melalui properti enumerasi objek, dan bukan indeks array. Pesanan tidak dijamin , bahkan dalam ES2015 (ES6). ES2015 menentukan urutan properti suatu objek (menggunakan [[OwnPropertyKeys]] , [[Enumerate]] , dan hal-hal yang menggunakannya sebagai Object.getOwnPropertyKeys ), tetapi ia tidak menentukan bahwa for-in akan mengikuti urutan itu. (Detail dalam jawaban lain ini .)

Namun, ini bisa berguna, terutama untuk array jarang , jika Anda menggunakan tindakan pencegahan yang sesuai:

 // 'a' is a sparse array var key; var a = []; a[0] = "a"; a[10] = "b"; a[10000] = "c"; for (key in a) { if (a.hasOwnProperty(key)  // These are explained /^0$|^[1-9]\d*$/.test(key)  // and then hidden key <= 4294967294 // away below ) { console.log(a[key]); } } 

Perhatikan dua cek:

  1. Bahwa objek memiliki properti sendiri di bawah nama ini (dan bukan yang diwarisi dari prototipe), dan

  2. Bahwa kuncinya adalah string numerik basis-10 dalam bentuk string yang biasanya, dan nilainya <= 2 ^ 32 - 2 (yaitu 4.294.967.294). Dari mana asal nomor ini? Ini adalah bagian dari definisi indeks array dalam spesifikasi . Angka lain (angka non-integer, angka negatif, angka lebih besar dari 2 ^ 32 - 2) bukan indeks array. Penyebab 2 ^ 32 - 2 adalah apa yang membuat nilai indeks tertinggi kurang dari 2 ^ 32 - 1 , yang merupakan nilai maksimum length array. (Misalnya, panjang array sesuai dengan integer unsigned 32-bit.) (Konfirmasi dari RobG untuk menunjukkan dalam komentar ke posting blog saya bahwa tes saya sebelumnya tidak tepat).

Ini adalah sedikit overhead tambahan untuk setiap iterasi loop pada kebanyakan array, tetapi jika Anda memiliki array yang jarang, ini mungkin cara yang lebih efisien untuk mengu>"0" , "10" dan "10000" - ingat, ini adalah garis), dan bukan 10.001 kali.

Sekarang Anda tidak ingin menulisnya setiap waktu, jadi Anda bisa memasukkannya ke dalam perangkat Anda:

 function arrayHasOwnIndex(array, prop) { return array.hasOwnProperty(prop)  /^0$|^[1-9]\d*$/.test(prop)  prop <= 4294967294; // 2^32 - 2 } 

Dan kemudian kita akan menggunakannya seperti ini:

 for (key in a) { if (arrayHasOwnIndex(a, key)) { console.log(a[key]); } } 

Atau, jika Anda hanya tertarik pada tes "cukup baik untuk kebanyakan kasus", Anda dapat menggunakannya, tetapi selama dekat, ini tidak sepenuhnya benar:

 for (key in a) { // "Good enough" for most cases if (String(parseInt(key, 10)) === key  a.hasOwnProperty(key)) { console.log(a[key]); } } 

4. Gunakan for-of (gunakan iterator implisit) (ES2015 +)

ES2015 menambahkan iterators ke JavaScript. Cara termudah untuk menggunakan iterator adalah operator baru. Ini terlihat seperti ini:

 var val; var a = ["a", "b", "c"]; for (val of a) { console.log(val); } 

Kesimpulan:

 a b c

Di bawah selimut, yang mendapatkan iterator dari array dan melewatinya, mendapat nilai dari itu. Ia tidak memiliki masalah dengan menggunakan for-in , karena ia menggunakan iterator yang didefinisikan oleh objek (array), dan array menentukan bahwa iterator mereka mengu>for-in di ES5, urutan di mana catatan dilihat adalah urutan numerik dari indeks mereka.

5. Gunakan iterator secara eksplisit (ES2015 +)

Terkadang Anda bisa secara eksplisit menggunakan iterator. Anda dapat melakukan ini juga, meskipun jauh lebih clunkier daripada for-of . Ini terlihat seperti ini:

 var a = ["a", "b", "c"]; var it = a.values(); var entry; while (!(entry = it.next()).done) { console.log(entry.value); } 

Iterator adalah objek yang cocok dengan definisi Iterator dalam spesifikasi. Metode next mengembalikan objek hasil baru setiap kali Anda menyebutnya. Objek hasil memiliki properti, done , memberi tahu kami apakah itu dilakukan, dan value properti dengan nilai untuk iterasi ini. ( done opsional jika itu false , value opsional jika tidak undefined ).

value bervariasi tergantung pada iterator; dukungan array (setidaknya) tiga fungsi yang mengembalikan iterator:

  • values() : Ini yang saya gunakan di atas. Ini mengembalikan iterator, di mana setiap value adalah catatan array untuk iterasi ini ( "a" , "b" dan "c" pada contoh di atas).
  • keys() : Mengembalikan iterator, di mana setiap value adalah kunci untuk iterasi ini (jadi untuk kita di atas, akan ada "0" , dan kemudian "1" , dan kemudian "2" ).
  • entries() : mengembalikan iterator, di mana setiap value adalah array dalam bentuk [key, value] untuk iterasi ini.

Untuk objek seperti array

Selain array yang benar, ada juga objek mirip array yang memiliki properti length dan properti dengan nama numerik: instance NodeList , objek arguments , dll. Bagaimana kita NodeList isinya?

Gunakan salah satu parameter di atas untuk array.

Setidaknya beberapa, dan mungkin sebagian besar atau bahkan semua array di atas sering digunakan dengan baik untuk objek tipe array:

  1. Gunakan forEach dan terkait (ES5 +)

    Berbagai fungsi pada Array.prototype "sengaja dibuat generik" dan biasanya dapat digunakan untuk objek seperti array melalui Function#call Function#apply atau Function#apply . (Lihat Penafian untuk objek yang disediakan oleh tuan rumah di akhir tanggapan ini, tetapi ini adalah masalah yang jarang terjadi.)

    Misalkan Anda ingin menggunakan forEach di childNodes Node childNodes . Anda akan melakukan ini:

     Array.prototype.forEach.call(node.childNodes, function(child) { // Do something with 'child' }); 

    Jika Anda akan sering melakukan ini, Anda mungkin ingin mendapatkan salinan referensi fungsi dalam variabel yang akan digunakan kembali, misalnya:

     // (This is all presumably in some scoping function) var forEach = Array.prototype.forEach; // Then later... forEach.call(node.childNodes, function(child) { // Do something with 'child' }); 
  2. Gunakan simpel for loop

    Jelas, sederhana for loop diterapkan pada objek seperti array.

  3. Gunakan dengan benar for-in

    for-in dengan jaminan yang sama dengan array, harus bekerja dengan objek yang mirip dengan array; Pemesanan mungkin diperlukan untuk item yang disediakan oleh tuan rumah ke nomor 1 di atas.

  4. Gunakan for-of (gunakan implisit iterator) (ES2015 +)

    for-of akan menggunakan iterator yang disediakan oleh objek (jika ada); kita harus melihat bagaimana ini terjadi dengan berbagai objek mirip array, terutama dengan file host. Misalnya, spesifikasi untuk NodeList dari querySelectorAll diperbarui untuk mendukung iterasi. Spesifikasi untuk HTMLCollection dari getElementsByTagName tidak.

  5. Gunakan iterator secara eksplisit (ES2015 +)

    Lihat nomor 4, kita perlu melihat bagaimana iterator dibuka.

Buat array yang benar

Dalam kasus lain, Anda bisa mengonversi objek seperti array menjadi array yang benar. Sangat mudah untuk melakukan ini:

  1. Gunakan metode array slice

    Kita dapat menggunakan metode array slice , yang, seperti metode lain yang disebutkan di atas, "sengaja dibuat generik" dan karenanya dapat digunakan dengan objek mirip array, misalnya:

     var trueArray = Array.prototype.slice.call(arrayLikeObject); 

    Jadi, misalnya, jika kita ingin mengonversi NodeList menjadi array nyata, kita bisa melakukan ini:

     var divs = Array.prototype.slice.call(document.querySelectorAll("div")); 

    Lihat "Perhatian untuk objek yang disediakan host" di bawah ini. Secara khusus, perhatikan bahwa ini tidak akan berfungsi di IE8 dan sebelumnya, yang tidak memungkinkan penggunaan objek yang disediakan oleh host seperti this .

  2. Gunakan sintaksis distribusi ( ... )

    Dimungkinkan juga untuk menggunakan sintaks distribusi ES2015 dengan mekanisme JavaScript yang mendukung fitur ini:

     var trueArray = [...iterableObject]; 

    Jadi, misalnya, jika kita ingin mengonversi NodeList menjadi array yang benar, dengan sintaks propagasi, itu menjadi agak singkat:

     var divs = [...document.querySelectorAll("div")]; 
  3. Gunakan Array.from (spec) | (MDN)

    Array.from (ES2015 +, tetapi mudah diisi poli) membuat array dari objek seperti array, jika perlu, pertama-tama melewati catatan melalui fungsi yang cocok. Jadi:

     var divs = Array.from(document.querySelectorAll("div")); 

    Atau, jika Anda ingin mendapatkan array nama tag untuk elemen dengan kelas yang diberikan, Anda harus menggunakan fungsi pemetaan:

     // Arrow function (ES2015): var divs = Array.from(document.querySelectorAll(".some-class"), element => element.tagName); // Standard function (since 'Array.from' can be shimmed): var divs = Array.from(document.querySelectorAll(".some-class"), function(element) { return element.tagName; }); 

Perhatian untuk fasilitas yang disediakan oleh tuan rumah

Jika Anda menggunakan fungsi Array.prototype dengan objek seperti host (daftar DOM dan hal-hal lain yang disediakan oleh browser, daripada mesin JavaScript), Anda harus memastikan untuk menguji di lingkungan target Anda untuk memastikan objek host yang disediakan berperilaku benar. Sebagian besar dari mereka berperilaku dengan benar (sekarang), tetapi penting untuk memeriksanya. Alasannya adalah bahwa sebagian besar metode Array.prototype yang mungkin ingin Anda gunakan bergantung pada objek yang disediakan oleh tuan rumah, memberikan jawaban jujur ​​pada abstrak [[HasProperty]] . Pada saat penulisan ini, browser melakukan pekerjaan dengan sangat baik, tetapi spesifikasi 5.1 menyarankan bahwa objek yang disediakan oleh tuan rumah mungkin tidak adil. Ini ada di §8.6.2 , beberapa paragraf di bawah tabel besar di awal bagian ini, di mana dikatakan:

Objek host dapat mengimplementasikan metode internal ini dengan cara apa pun kecuali jika dinyatakan sebaliknya; misalnya, satu kemungkinan adalah bahwa [[Get]] dan [[Put]] untuk objek host tertentu memang mengambil dan menyimpan nilai properti, tetapi [[HasProperty]] selalu menghasilkan false .

(Saya tidak dapat menemukan kata-kata yang ekivalen dalam spesifikasi ES2015, tetapi masih harus seperti itu.) Sekali lagi, seperti dengan menulis host bersama dari array tipe objek yang disediakan di browser modern [contoh NodeList , misalnya], membuat [[HasProperty]] menangani dengan benar, tetapi penting periksa.)

6292
17 февр. Jawabannya diberikan oleh TJ Crowder 17 Feb. 2012-02-17 16:53 '12 pada pukul 16:53 2012-02-17 16:53

Sunting : jawaban ini sudah ketinggalan zaman. Untuk pendekatan yang lebih modern, lihat metode yang tersedia dalam array . Metode yang menarik mungkin:

  • untuk masing-masing
  • kartu
  • filter
  • pengikat zip
  • untuk mengurangi
  • setiap
  • sedikit

Cara standar untuk mengu>JavaScript adalah for -loop vanilla:

 var length = arr.length, element = null; for (var i = 0; i < length; i++) { element = arr[i]; // Do something with element } 

Perhatikan, bagaimanapun, bahwa pendekatan ini hanya baik jika Anda memiliki array yang padat, dan setiap indeks ditempati oleh suatu elemen. Jika array jarang, maka dengan pendekatan ini Anda dapat mengalami masalah kinerja, karena Anda akan melalui banyak indeks yang sebenarnya tidak ada dalam array. Dalam hal ini, lebih baik digunakan for.. in -loop. Namun, Anda harus menggunakan tindakan pencegahan yang sesuai untuk memastikan bahwa hanya properti array yang diperlukan (yaitu elemen array) yang for..in , karena for..in -loop juga akan terdaftar di browser lawas, atau jika properti tambahan didefinisikan sebagai enumerable .

Dalam ECMAScript 5 , metode forEach akan digunakan untuk prototipe array, tetapi tidak didukung di browser lama. Oleh karena itu, untuk dapat menggunakannya secara konsisten, Anda harus memiliki lingkungan yang mendukungnya (misalnya, Node.js untuk JavaScript sisi-server), atau gunakan "Polyfill". Namun, Polyfill untuk fungsi ini sepele, dan karena membuat kode lebih mudah dibaca, maka harus dimasukkan dalam Polyfill.

470
17 февр. Balas diberikan oleh PatrikAkerstrand pada 17 Feb. 2012-02-17 16:55 '12 pada pukul 16:55 2012-02-17 16:55

Jika Anda menggunakan perpustakaan jQuery , Anda dapat menggunakan jQuery.each :

214
17 февр. Jawabannya diberikan Poonam 17 Feb. 2012-02-17 17:01 '12 pada 17:01 2012-02-17 17:01

Loop kembali

Saya pikir kebalikan dari siklus ini layak disebutkan di sini:

 for (var i = array.length; i--; ) { // process array[i] } 

Manfaat:

  • Anda tidak perlu mendeklarasikan variabel sementara len atau membandingkannya dengan array.length pada setiap iterasi, yang dapat berupa optimasi menit.
  • Menghapus saudara kandung dari DOM dalam urutan terbalik biasanya lebih efisien . (Peramban perlu memindahkan lebih sedikit elemen dalam array internal.)
  • Jika Anda mengubah array selama loop, pada atau setelah indeks I (misalnya, Anda menghapus atau memasukkan elemen ke dalam array[i] ), maka loop >solusi yang lebih sederhana dan lebih elegan .
  • Demikian pula, ketika mengubah atau menghapus elemen DOM bersarang , pemrosesan balik dapat mem - bypass kesalahan . Misalnya, pertimbangkan untuk mengubah innerHTML dari simpul induk sebelum memproses anak-anaknya. Pada saat simpul anak tercapai, ia akan dipisahkan dari DOM, menggantikannya dengan keturunan baru ketika parentHTHTML ditulis.
  • lebih pendek dan membaca daripada beberapa opsi lain yang tersedia. Meskipun kalah dari forEach() dan ES6 for ... of .

Kekurangan:

  • Ini memproses item dalam urutan terbalik. Jika Anda membuat array baru dari hasil atau dicetak di layar, output tentu saja akan dibatalkan relatif terhadap pesanan awal.
  • Неоднократно вставляя братьев и сестер в DOM в качестве первого ребенка, чтобы сохранить их порядок, менее эффективен . (В браузере все равно придется перекладывать вещи.) Чтобы создавать узлы DOM эффективно и упорядоченно, просто переходите вперед и добавьте как обычно (а также используйте "фрагмент документа" ).
  • Обратный цикл запутывает для младших разработчиков. (Вы можете считать это преимущество, в зависимости от вашего прогноза.)

Должен ли я всегда использовать его?