Untuk setiap array dalam JavaScript


4684

Bagaimana saya bisa mengulang semua entri dalam array menggunakan JavaScript?

Saya pikir itu kira-kira seperti ini:

forEach(instance in theArray)

Di mana theArrayarray saya, tetapi ini tampaknya salah.


16
Saya memang mencarinya, tetapi saya mencarinya forEach dan bukan hanya for. seperti yang dinyatakan, dalam c # itu sedikit berbeda, dan itu membingungkan saya :)
Dante1986

6
ECMAScript & nbsp; 6 mungkin akan mengandung konstruk "for ... of". Lihat ... dari (MDN) untuk informasi lebih lanjut. Anda sudah dapat mencobanya dengan versi Firefox terbaru.
Slaven Rezic

36
Array.ForEach sekitar 95% lebih lambat daripada untuk () di untuk masing-masing untuk Array dalam JavaScript. Lihat tes kinerja ini secara online: jsperf.com/fast-array-foreach via coderwall.com/p/kvzbpa
molokoloco

77
Bagi banyak situasi yang 95% lebih lambat tidak akan signifikan blog.niftysnippets.org/2012/02/foreach-and-runtime-cost.html
David Sykes

7
Sebaliknya, di Python itu lebih efisien untuk menggunakan fungsi daripada penggunaan tradisional untuk loop. (Pertimbangkan itu i < lendan i++dapat dilakukan oleh mesin, bukan oleh penerjemah.)
joeytwiddle

Jawaban:


7022

TL; DR

  • Jangan gunakan for-inkecuali Anda menggunakannya dengan perlindungan atau setidaknya menyadari mengapa itu bisa menggigit Anda.
  • Taruhan terbaik Anda biasanya

    • sebuah for-ofloop (ES2015 + saja),
    • Array#forEach( spec| MDN) (atau saudara somedan sejenisnya) (hanya ES5 +),
    • forloop kuno sederhana ,
    • atau for-indengan perlindungan.

Tetapi ada banyak lagi untuk dijelajahi, baca terus ...


JavaScript memiliki semantik yang kuat untuk perulangan melalui array dan objek seperti array. Saya telah membagi jawaban menjadi dua bagian: Opsi untuk array asli, dan opsi untuk hal-hal yang hanya seperti array , seperti argumentsobjek, objek iterable lainnya (ES2015 +), koleksi DOM, dan sebagainya.

Aku akan segera dicatat bahwa Anda dapat menggunakan ES2015 pilihan sekarang , bahkan pada mesin ES5, oleh transpiling ES2015 untuk ES5. Cari "ES2015 transpiling" / "ES6 transpiling" untuk lebih ...

Oke, mari kita lihat opsi kami:

Untuk Array Aktual

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 forEachdan terkait (ES5 +)
  2. Gunakan forloop sederhana
  3. Gunakan for-in dengan benar
  4. Gunakan for-of(gunakan iterator secara implisit) (ES2015 +)
  5. Gunakan iterator secara eksplisit (ES2015 +)

Detail:

1. Gunakan forEachdan terkait

Di lingkungan samar-samar modern (jadi, bukan IE8) di mana Anda memiliki akses ke Arrayfitur yang ditambahkan oleh ES5 (langsung atau menggunakan polyfill), Anda dapat menggunakan forEach( spec| MDN):

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

forEachmenerima fungsi panggilan balik dan, secara opsional, nilai yang digunakan seperti thissaat memanggil panggilan balik itu (tidak digunakan di atas). Callback dipanggil untuk setiap entri dalam array, secara berurutan, melewatkan entri yang tidak ada dalam array jarang. Meskipun saya hanya menggunakan satu argumen di atas, callback dipanggil dengan tiga: Nilai setiap entri, indeks entri itu, dan referensi ke array yang Anda iterasi (jika fungsi Anda belum membuatnya berguna) ).

Kecuali jika Anda mendukung peramban usang seperti IE8 (yang NetApps tunjukkan di lebih dari 4% pangsa pasar pada tulisan ini pada September 2016), Anda dapat dengan senang hati menggunakan forEachlaman web tujuan umum tanpa shim. Jika Anda perlu mendukung browser yang usang, shimming / polyfilling forEachmudah dilakukan (cari "es5 shim" untuk beberapa opsi).

forEach memiliki manfaat bahwa Anda tidak harus mendeklarasikan pengindeksan dan nilai variabel dalam lingkup yang berisi, karena mereka disediakan sebagai argumen untuk fungsi iterasi, dan sangat baik hanya untuk iterasi itu.

Jika Anda khawatir tentang biaya runtime untuk membuat panggilan fungsi untuk setiap entri array, jangan; detail .

Selain itu, forEachadalah fungsi "loop through them all", tetapi ES5 mendefinisikan beberapa fungsi lain yang bermanfaat "bekerja dengan cara Anda melalui array dan melakukan sesuatu" fungsi, termasuk:

  • every(berhenti mengulang-ulang saat panggilan balik kembali falseatau sesuatu yang palsu)
  • some(berhenti mengulang-ulang saat panggilan balik kembali trueatau sesuatu yang benar)
  • filter(membuat array baru termasuk elemen tempat fungsi filter kembali truedan menghilangkan yang mengembalikannya false)
  • map (membuat array baru dari nilai yang dikembalikan oleh callback)
  • reduce (membangun nilai dengan berulang kali memanggil callback, meneruskan nilai sebelumnya; lihat spesifikasi untuk detail; berguna untuk menjumlahkan isi array dan banyak hal lainnya)
  • reduceRight(seperti reduce, tetapi bekerja dalam urutan menurun daripada urutan naik)

2. Gunakan forloop sederhana

Terkadang cara lama adalah yang terbaik:

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

Jika panjang array tidak akan berubah selama loop, dan itu dalam kode kinerja sensitif (mungkin), versi yang sedikit lebih rumit meraih panjang depan mungkin kecil 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 mundur:

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

Tetapi dengan mesin JavaScript modern, jarang Anda perlu menambah sedikit jus terakhir.

Di ES2015 dan lebih tinggi, Anda bisa membuat indeks dan variabel nilai lokal ke forloop:

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

Dan ketika Anda melakukan itu, bukan hanya valuetetapi juga indexdiciptakan kembali untuk setiap iterasi loop, artinya penutupan yang dibuat dalam tubuh loop tetap mengacu pada index(dan value) yang dibuat untuk iterasi spesifik:

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

Jika Anda memiliki lima div, Anda akan mendapatkan "Indeks adalah: 0" jika Anda mengklik yang pertama dan "Indeks adalah: 4" jika Anda mengklik yang terakhir. Ini tidak berfungsi jika Anda menggunakannya varsebagai gantinya let.

3. Gunakan for-in dengan benar

Anda akan mendapatkan orang memberitahu Anda untuk menggunakan for-in, tapi bukan itu yang for-inbagi . for-inloop melalui properti enumerable suatu objek , bukan indeks array. Pesanan tidak dijamin , bahkan dalam ES2015 (ES6). ES2015 + tidak menentukan untuk properti obyek (melalui [[OwnPropertyKeys]], [[Enumerate]]dan hal-hal yang menggunakannya seperti Object.getOwnPropertyKeys), tapi itu tidak menentukan bahwa for-inakan mengikuti perintah itu; ES2020 melakukannya. (Detail dalam jawaban lain ini .)

Satu-satunya kasus penggunaan nyata untuk for-inpada array adalah:

  • Ini array jarang dengan celah besar di dalamnya, atau
  • Anda menggunakan properti non-elemen dan Anda ingin memasukkannya dalam loop

Melihat hanya pada contoh pertama itu: Anda dapat menggunakan for-inuntuk mengunjungi elemen array yang jarang itu jika Anda menggunakan pengamanan 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 checks are
        /^0$|^[1-9]\d*$/.test(key) &&    // explained
        key <= 4294967294                // below
        ) {
        console.log(a[key]);
    }
}

Perhatikan tiga cek:

  1. Bahwa objek memiliki properti sendiri dengan nama itu (bukan yang diwarisi dari prototipe), dan

  2. Bahwa kuncinya adalah semua digit desimal (misalnya, bentuk string normal, bukan notasi ilmiah), dan

  3. Bahwa nilai kunci ketika dipaksa ke suatu angka adalah <= 2 ^ 32 - 2 (yaitu 4.294.967.294). Dari mana angka itu berasal? Itu bagian dari definisi indeks array dalam spesifikasi . Angka lain (bukan bilangan bulat, angka negatif, angka lebih besar dari 2 ^ 32 - 2) bukan indeks array. Alasannya adalah 2 ^ 32 - 2 adalah yang membuat nilai indeks terbesar lebih rendah dari 2 ^ 32 - 1 , yang merupakan nilai maksimum yang dimiliki sebuah array length. (Misalnya, panjang array cocok dengan bilangan bulat 32-bit unsigned.) (Props untuk RobG untuk menunjukkan dalam komentar di posting blog saya bahwa tes saya sebelumnya tidak benar.)

Anda tidak akan melakukannya dalam kode inline, tentu saja. Anda akan menulis fungsi utilitas. Mungkin:

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

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

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

Di bawah selimut, yang mendapatkan iterator dari array dan loop melalui itu, mendapatkan nilai dari itu. Ini tidak memiliki masalah yang menggunakan for-intelah, karena menggunakan iterator yang ditentukan oleh objek (array), dan array menentukan bahwa iterator mereka mengulangi melalui entri mereka (bukan properti mereka). Tidak seperti for-inES5, urutan entri yang dikunjungi adalah urutan numerik indeks mereka.

5. Gunakan iterator secara eksplisit (ES2015 +)

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

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

Iterator adalah objek yang cocok dengan definisi Iterator dalam spesifikasi. Its nextmetode mengembalikan baru hasil objek setiap kali Anda menyebutnya. Objek hasil memiliki properti, donememberi tahu kami apakah itu dilakukan, dan properti valuedengan nilai untuk iterasi itu. ( doneadalah opsional jika itu akan false, valueadalah opsional jika itu akan terjadi undefined.)

Arti valuebervariasi tergantung pada iterator; dukungan array (setidaknya) tiga fungsi yang mengembalikan iterator:

  • values(): Ini yang saya gunakan di atas. Ini mengembalikan sebuah iterator di mana setiap valueadalah entri array untuk iterasi yang ( "a", "b", dan "c"dalam contoh sebelumnya).
  • keys(): Mengembalikan iterator di mana masing value- masing adalah kunci untuk iterasi itu (jadi untuk di aatas kita , itu akan menjadi "0", lalu "1", lalu "2").
  • entries(): Mengembalikan iterator di mana masing value- masing adalah array dalam bentuk [key, value]untuk iterasi itu.

Untuk Objek Seperti Array

Selain dari array yang benar, ada juga objek seperti array yang memiliki lengthproperti dan properti dengan nama numerik: NodeListinstance, argumentsobjek, dll. Bagaimana cara kita menelusuri isinya?

Gunakan salah satu opsi di atas untuk array

Setidaknya beberapa, dan mungkin sebagian besar atau bahkan semua, pendekatan array di atas sering berlaku sama baiknya untuk objek seperti array:

  1. Gunakan forEachdan terkait (ES5 +)

    Berbagai fungsi pada Array.prototype"sengaja generik" dan biasanya dapat digunakan pada objek mirip array melalui Function#callatau Function#apply. (Lihat Peringatan untuk objek yang disediakan oleh tuan rumah di akhir jawaban ini, tetapi ini adalah masalah yang jarang terjadi.)

    Misalkan Anda ingin menggunakan forEachpada Node's childNodesproperti. Anda akan melakukan ini:

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

    Jika Anda akan sering melakukannya, Anda mungkin ingin mengambil salinan referensi fungsi ke dalam variabel untuk 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 forloop sederhana

    Jelas, forloop sederhana berlaku untuk objek mirip array.

  3. Gunakan for-in dengan benar

    for-indengan perlindungan yang sama dengan array harus bekerja dengan objek seperti array juga; peringatan untuk objek yang disediakan oleh host pada # 1 di atas mungkin berlaku.

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

    for-ofmenggunakan iterator yang disediakan oleh objek (jika ada). Itu termasuk objek yang disediakan host. Misalnya, spesifikasi untuk NodeListdari querySelectorAlltelah diperbarui untuk mendukung iterasi. Spesifikasi untuk HTMLCollectiondari getElementsByTagNametidak.

  5. Gunakan iterator secara eksplisit (ES2015 +)

    Lihat # 4.

Buat array yang benar

Di lain waktu, Anda mungkin ingin mengubah objek mirip array menjadi array yang benar. Melakukan hal itu sangat mudah:

  1. Gunakan slicemetode array

    Kita dapat menggunakan slicemetode array, yang seperti metode lain yang disebutkan di atas adalah "sengaja generik" dan dapat digunakan dengan objek seperti array, seperti ini:

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

    Jadi misalnya, jika kita ingin mengkonversi NodeListmenjadi array yang benar, kita bisa melakukan ini:

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

    Lihat Peringatan untuk objek yang disediakan oleh host di bawah ini. Secara khusus, perhatikan bahwa ini akan gagal di IE8 dan sebelumnya, yang tidak memungkinkan Anda menggunakan objek yang disediakan host thisseperti itu.

  2. Gunakan sintaksis sebar ( ...)

    Dimungkinkan juga untuk menggunakan sintaksis penyebaran ES2015 dengan mesin JavaScript yang mendukung fitur ini. Seperti for-of, ini menggunakan iterator yang disediakan oleh objek (lihat # 4 di bagian sebelumnya):

    var trueArray = [...iterableObject];

    Jadi misalnya, jika kita ingin mengkonversi NodeListmenjadi array yang benar, dengan menyebar sintaks ini menjadi sangat ringkas:

    var divs = [...document.querySelectorAll("div")];
  3. Menggunakan Array.from

    Array.from (spec) | (MDN) (ES2015 +, tetapi mudah di-polyfilled) membuat array dari objek mirip array, secara opsional meneruskan entri melalui fungsi pemetaan terlebih dahulu. Begitu:

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

    Atau jika Anda ingin mendapatkan array nama tag elemen dengan kelas yang diberikan, Anda akan 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;
    });
    

Peringatan untuk objek yang disediakan oleh host

Jika Anda menggunakan Array.prototypefungsi dengan objek mirip array yang disediakan host (daftar DOM dan hal-hal lain yang disediakan oleh browser daripada mesin JavaScript), Anda perlu memastikan untuk menguji di lingkungan target Anda untuk memastikan objek yang disediakan host bertindak dengan benar . Sebagian besar berperilaku baik (sekarang), tetapi penting untuk menguji. Alasannya adalah bahwa sebagian besar Array.prototypemetode yang Anda ingin gunakan bergantung pada objek yang disediakan host memberikan jawaban jujur ​​untuk [[HasProperty]]operasi abstrak . Pada tulisan ini, browser melakukan pekerjaan yang sangat baik ini, tetapi spesifikasi 5.1 memang memungkinkan untuk kemungkinan objek yang disediakan host mungkin tidak jujur. Ada dalam §8.6.2 , beberapa paragraf di bawah tabel besar di dekat awal bagian itu), di mana dikatakan:

Objek host dapat menerapkan metode internal ini dengan cara apa pun kecuali ditentukan lain; 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 bisa menemukan setara verbiage di ES2015 spec, tapi itu pasti masih menjadi kasus.) Sekali lagi, seperti tulisan ini umum host-disediakan array seperti objek dalam browser modern [ NodeListcontoh, misalnya] lakukan pegangan [[HasProperty]]dengan benar, tetapi penting untuk menguji.)


44
Saya juga ingin menambahkan bahwa .forEachtidak dapat rusak secara efisien. Anda harus melempar pengecualian untuk melakukan break.
Pijusn

82
@Pius: Jika Anda ingin memutus perulangan, Anda dapat menggunakan some. (Saya lebih suka membiarkan istirahat forEachjuga, tetapi mereka, um, tidak bertanya kepada saya. ;-))
TJ Crowder

6
@TJCrowder Benar, meskipun itu lebih seperti solusi karena ini bukan tujuan utamanya.
Pijusn

8
@ user889030: Anda perlu ,after k=0, bukan a ;. Ingat, pemrograman adalah banyak hal, salah satunya adalah perhatian terhadap detail ... :-)
TJ Crowder

5
@ JimB: Itu dibahas di atas (dan lengthbukan metode). :-)
TJ Crowder

513

Catatan : Jawaban ini sudah ketinggalan zaman. Untuk pendekatan yang lebih modern, lihat metode yang tersedia di array . Metode yang menarik mungkin:

  • untuk setiap
  • peta
  • Saring
  • zip
  • mengurangi
  • setiap
  • beberapa

Cara standar untuk mengulangi array dalam JavaScript adalah vanilla for-loop:

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 Anda dapat mengalami masalah kinerja dengan pendekatan ini, karena Anda akan mengulangi banyak indeks yang tidak benar - benar ada dalam array. Dalam hal ini, for .. in-loop mungkin ide yang lebih baik. Namun , Anda harus menggunakan perlindungan yang sesuai untuk memastikan bahwa hanya properti array yang diinginkan (yaitu, elemen array) yang ditindaklanjuti, karena for..in-loop juga akan disebutkan dalam browser lama, atau jika properti tambahan didefinisikan sebagai enumerable.

Dalam ECMAScript 5 akan ada metode forEach pada prototipe array, tetapi tidak didukung di browser lawas. Jadi untuk dapat menggunakannya secara konsisten, Anda harus memiliki lingkungan yang mendukungnya (misalnya, Node.js untuk JavaScript sisi server), atau menggunakan "Polyfill". Namun, Polyfill untuk fungsi ini sepele dan karena membuat kode lebih mudah dibaca, itu adalah polyfill yang baik untuk dimasukkan.


2
mengapa for(instance in objArray) penggunaannya tidak benar? itu terlihat lebih sederhana bagi saya, tetapi saya mendengar Anda berbicara tentang itu bukan cara yang benar untuk digunakan?
Dante1986

21
Anda dapat menggunakan caching panjang sebaris: untuk (var i = 0, l = arr.length; i <l; i ++)
Robert Hoffmann

3
Apakah koma pada akhir baris pertama disengaja, atau apakah itu salah ketik (bisa titik koma)?
Mohd Abdul Mujib

6
@ wardha-Web Ini disengaja. Ini memungkinkan kita untuk mendeklarasikan banyak variabel dengan satu kata kunci var. Jika kita menggunakan titik koma, maka elementakan dinyatakan dalam lingkup global (atau, lebih tepatnya, JSHint akan meneriaki kita sebelum mencapai produksi).
PatrikAkerstrand

239

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

$.each(yourArray, function(index, value) {
  // do your stuff here
});

EDIT:

Sesuai pertanyaan, pengguna menginginkan kode dalam javascript alih-alih jquery sehingga hasil editnya

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

2
Saya mungkin akan menggunakan jawaban ini paling sering. Ini bukan jawaban terbaik untuk pertanyaan, tetapi dalam praktiknya akan menjadi yang paling sederhana dan paling berlaku bagi kita yang menggunakan jQuery. Saya pikir kita semua harus belajar cara vanila juga. Tidak ada salahnya untuk memperluas pemahaman Anda.
mopsyd

47
Hanya demi itu: masing-masing jQuery jauh lebih lambat daripada solusi asli. Disarankan oleh jQuery untuk menggunakan JavaScript asli alih-alih jQuery jika memungkinkan. jsperf.com/browser-diet-jquery-each-vs-for-loop
Kevin Boss

8
Jangan menggunakan jQuery saat Anda dapat menggunakan vanilla js
Noe

2
Tetap berpegang pada JS standar, jauhkan perpustakaan pihak ke-3 dari jawabannya kecuali jika tidak ada solusi bahasa asli
scubasteve

116

Loop ke belakang

Saya pikir sebaliknya untuk loop layak disebutkan di sini:

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

Keuntungan:

  • Anda tidak perlu mendeklarasikan lenvariabel sementara , atau membandingkannya array.lengthpada setiap iterasi, yang keduanya mungkin merupakan pengoptimalan menit.
  • Menghapus saudara kandung dari DOM dalam urutan terbalik biasanya lebih efisien . (Peramban perlu mengurangi pergeseran elemen dalam susunan internalnya.)
  • Jika Anda memodifikasi array saat pengulangan, pada atau setelah indeks i (misalnya Anda menghapus atau menyisipkan item di array[i]), maka pengulangan akan melewatkan item yang bergeser ke kiri ke posisi i , atau memproses ulang item ke- i yang sebelumnya bergeser ke kanan. Dalam perulangan tradisional, Anda dapat memperbarui saya untuk menunjuk ke item berikutnya yang perlu diproses - 1, tetapi hanya membalikkan arah iterasi seringkali merupakan solusi yang lebih sederhana dan lebih elegan .
  • Demikian pula, ketika memodifikasi atau menghapus elemen DOM bersarang , pemrosesan secara terbalik dapat menghindari kesalahan . Misalnya, pertimbangkan untuk memodifikasi innerHTML dari simpul induk sebelum menangani anak-anaknya. Pada saat simpul anak tercapai, simpul itu akan terlepas dari DOM, yang telah digantikan oleh anak yang baru dibuat ketika innerHTML induknya ditulis.
  • Ini lebih pendek untuk mengetik, dan membaca , daripada beberapa opsi lain yang tersedia. Meskipun kalah dari forEach()dan ke ES6 for ... of.

Kekurangan:

  • Ini memproses item dalam urutan terbalik. Jika Anda sedang membangun array baru dari hasil, atau mencetak hal-hal di layar, tentu saja hasilnya akan terbalik sehubungan dengan pesanan asli.
  • Berulang kali memasukkan saudara kandung ke dalam DOM sebagai anak pertama untuk mempertahankan pesanan mereka kurang efisien . (Peramban akan tetap harus mengubah hal-hal dengan benar.) Untuk membuat simpul DOM secara efisien dan berurutan, hanya loop ke depan dan tambahkan seperti biasa (dan juga menggunakan "fragmen dokumen").
  • Loop terbalik membingungkan bagi pengembang junior. (Anda dapat menganggap itu suatu keuntungan, tergantung pada pandangan Anda.)

Haruskah saya selalu menggunakannya?

Beberapa pengembang menggunakan reverse for loop secara default , kecuali ada alasan bagus untuk loop ke depan.

Meskipun keuntungan kinerja biasanya tidak signifikan, itu semacam jeritan:

"Lakukan saja ini untuk setiap item dalam daftar, aku tidak peduli dengan pesanannya!"

Namun dalam praktiknya itu sebenarnya bukan indikasi niat yang dapat diandalkan, karena itu tidak dapat dibedakan dari saat-saat ketika Anda benar-benar peduli dengan pesanan, dan benar-benar perlu mengulang secara terbalik. Jadi sebenarnya diperlukan konstruksi lain untuk secara akurat mengekspresikan maksud "tidak peduli", sesuatu yang saat ini tidak tersedia di sebagian besar bahasa, termasuk ECMAScript, tetapi yang dapat disebut, misalnya forEachUnordered(),.

Jika pesanan tidak masalah, dan efisiensi adalah masalah (di loop paling dalam dari game atau mesin animasi), maka mungkin dapat diterima untuk menggunakan reverse untuk loop sebagai pola masuk Anda. Ingatlah bahwa melihat pembalikan untuk loop dalam kode yang ada tidak selalu berarti bahwa urutannya tidak relevan!

Lebih baik menggunakan forEach ()

Secara umum untuk kode level yang lebih tinggi di mana kejelasan dan keamanan merupakan masalah yang lebih besar, saya sebelumnya merekomendasikan penggunaan Array::forEachsebagai pola default Anda untuk perulangan (meskipun hari ini saya lebih suka menggunakan for..of). Alasan untuk memilih forEachlebih dari loop terbalik adalah:

  • Lebih jelas untuk membaca.
  • Ini menunjukkan bahwa saya tidak akan bergeser di dalam blok (yang selalu merupakan kejutan yang mungkin bersembunyi lama fordan whileloop).
  • Ini memberi Anda ruang lingkup gratis untuk penutupan.
  • Ini mengurangi kebocoran variabel lokal dan tabrakan tidak disengaja dengan (dan mutasi) variabel luar.

Kemudian ketika Anda melihat pembalikan untuk loop dalam kode Anda, itu adalah petunjuk bahwa itu terbalik karena alasan yang baik (mungkin salah satu alasan yang dijelaskan di atas). Dan melihat ke depan tradisional untuk loop dapat menunjukkan bahwa pergeseran dapat terjadi.

(Jika pembahasan niat tidak masuk akal bagi Anda, maka Anda dan kode Anda mungkin mendapat manfaat dari menonton ceramah Crockford tentang Gaya Pemrograman & Otak Anda .)

Sekarang bahkan lebih baik untuk digunakan untuk ... dari!

Ada perdebatan tentang apakah for..ofatau forEach()lebih disukai:

  • Untuk dukungan peramban yang maksimal, for..of diperlukan polyfill untuk iterator, membuat aplikasi Anda sedikit lebih lambat untuk dieksekusi dan sedikit lebih besar untuk diunduh.

  • Karena alasan itu (dan untuk mendorong penggunaan mapdan filter), beberapa panduan gaya front-end dilarang for..ofsepenuhnya!

  • Tetapi masalah di atas tidak berlaku untuk aplikasi Node.js, di mana for..ofsekarang didukung dengan baik.

  • Dan selanjutnya await tidak bekerja di dalam forEach(). Penggunaan for..ofadalah pola paling jelas dalam kasus ini.

Secara pribadi, saya cenderung menggunakan apa pun yang terlihat paling mudah dibaca, kecuali kinerja atau minifikasi telah menjadi perhatian utama. Jadi hari ini saya lebih memilih untuk menggunakan for..ofbukan forEach(), tapi saya akan selalu menggunakan mapatau filteratau findatau someketika berlaku. (Demi kolega saya, saya jarang menggunakan reduce.)


Bagaimana cara kerjanya?

for (var i = 0; i < array.length; i++) { ... }   // Forwards

for (var i = array.length; i--; )    { ... }   // Reverse

Anda akan melihat bahwa itu i--adalah klausa tengah (di mana kita biasanya melihat perbandingan) dan klausa terakhir kosong (di mana kita biasanya melihat i++). Itu berarti yang i--juga digunakan sebagai syarat untuk kelanjutan. Yang terpenting, ini dieksekusi dan diperiksa sebelum setiap iterasi.

  • Bagaimana ini bisa dimulai array.lengthtanpa meledak?

    Karena i--berjalan sebelum setiap iterasi, pada iterasi pertama kita akan benar-benar mengakses item array.length - 1yang menghindari masalah dengan item Array-out-of-bounds undefined .

  • Mengapa tidak berhenti iterasi sebelum indeks 0?

    Loop akan berhenti iterasi ketika kondisi i--mengevaluasi ke nilai falsey (ketika menghasilkan 0).

    Kuncinya adalah bahwa tidak seperti --i, i--operator tambahan menurun itetapi menghasilkan nilai sebelum pengurangan. Konsol Anda dapat menunjukkan ini:

    > var i = 5; [i, i--, i];

    [5, 5, 4]

    Jadi pada iterasi terakhir, saya sebelumnya 1 dan i--ekspresi mengubahnya menjadi 0 tetapi sebenarnya menghasilkan 1 (benar), dan dengan demikian kondisinya lewat. Pada iterasi berikutnya i--perubahan i menjadi -1 tetapi menghasilkan 0 (falsey), menyebabkan eksekusi segera keluar dari bagian bawah loop.

    Dalam ke depan tradisional untuk loop, i++dan ++idapat dipertukarkan (seperti yang ditunjukkan Douglas Crockford). Namun dalam reverse for loop, karena penurunan kami juga merupakan ekspresi kondisi kami, kami harus tetap dengan i--jika kami ingin memproses item di indeks 0.


Hal sepele

Beberapa orang suka menggambar panah kecil di forloop terbalik , dan diakhiri dengan mengedipkan mata:

for (var i = array.length; i --> 0 ;) {

Kredit pergi ke WYL untuk menunjukkan kepada saya manfaat dan kengerian dari pembalikan untuk loop.


3
Saya lupa menambahkan tolok ukur . Saya juga lupa menyebutkan bagaimana reverse looping adalah optimasi yang signifikan pada prosesor 8-bit seperti 6502, di mana Anda benar-benar mendapatkan perbandingan secara gratis!
joeytwiddle

Jawaban yang sama diberikan jauh lebih ringkas di sini (pada pertanyaan yang berbeda).
joeytwiddle

84

Beberapa bahasa gaya- C digunakan foreachuntuk mengulang enumerasi. Dalam JavaScript ini dilakukan dengan for..instruktur loop :

var index,
    value;
for (index in obj) {
    value = obj[index];
}

Ada tangkapan. for..inakan loop melalui masing-masing anggota objek enumerable, dan anggota pada prototipe-nya. Untuk menghindari membaca nilai yang diwariskan melalui prototipe objek, cukup periksa apakah properti itu milik objek:

for (i in obj) {
    if (obj.hasOwnProperty(i)) {
        //do stuff
    }
}

Selain itu, ECMAScript 5 telah menambahkan forEachmetode Array.prototypeyang dapat digunakan untuk menghitung lebih dari satu array menggunakan calback (polyfill ada dalam dokumen sehingga Anda masih dapat menggunakannya untuk browser yang lebih lama):

arr.forEach(function (val, index, theArray) {
    //do stuff
});

Penting untuk dicatat bahwa Array.prototype.forEachtidak terputus ketika callback kembali false. jQuery dan Underscore.js menyediakan variasi sendiri eachuntuk menyediakan loop yang dapat dihubung pendek.


3
Jadi bagaimana seseorang keluar dari loop foreach ECMAScript5 seperti yang kita lakukan untuk loop normal atau loop foreach seperti yang ditemukan dalam bahasa C-style?
Ciaran Gallagher

5
@CiaranG, dalam JavaScript adalah hal biasa untuk melihat eachmetode yang memungkinkan return falsedigunakan untuk keluar dari loop, tetapi dengan forEachini bukanlah suatu pilihan. Bendera eksternal dapat digunakan (yaitu if (flag) return;, tetapi itu hanya akan mencegah sisa dari fungsi tubuh dari mengeksekusi, forEachmasih akan melanjutkan iterasi di seluruh koleksi.
zzzzBov

43

Jika Anda ingin mengulang array, gunakan forloop tiga bagian standar .

for (var i = 0; i < myArray.length; i++) {
    var arrayItem = myArray[i];
}

Anda bisa mendapatkan beberapa optimasi kinerja dengan melakukan caching myArray.lengthatau mengulanginya.


6
untuk (var i = 0, length = myArray.length; i <length; i ++) harus melakukannya
Edson Medina

5
@ EdsonMedina Itu juga akan membuat variabel global baru yang disebut length. ;)
joeytwiddle

4
@ joeytwiddle Ya, tapi itu di luar cakupan posting ini. Anda tetap akan membuat variabel global.
Edson Medina

6
@ EdsonMedina Permintaan maaf saya, saya salah besar. Menggunakan ,setelah penugasan tidak memperkenalkan global baru, jadi saran Anda baik - baik saja ! Saya membingungkan ini untuk masalah yang berbeda: Menggunakan =setelah tugas tidak membuat global baru.
joeytwiddle

Waspadai variabel saya bukan lokal untuk loop. JavaScript tidak memiliki ruang lingkup blokir. Mungkin lebih baik untuk mendeklarasikan var i, length, arrayItem;sebelum loop untuk menghindari kesalahpahaman ini.
James

35

Saya tahu ini adalah pos lama, dan sudah ada begitu banyak jawaban. Untuk sedikit lebih lengkap saya pikir saya akan melempar yang lain menggunakan AngularJS . Tentu saja, ini hanya berlaku jika Anda menggunakan Angular, jelas, toh saya tetap ingin mengatakannya.

angular.forEachmengambil 2 argumen dan argumen ketiga opsional. Argumen pertama adalah objek (array) untuk beralih, argumen kedua adalah fungsi iterator, dan argumen ketiga opsional adalah konteks objek (pada dasarnya disebut di dalam loop sebagai 'ini'.

Ada berbagai cara untuk menggunakan forEach loop of angular. Yang paling sederhana dan mungkin paling banyak digunakan adalah

var temp = [1, 2, 3];
angular.forEach(temp, function(item) {
    //item will be each element in the array
    //do something
});

Cara lain yang berguna untuk menyalin item dari satu array ke array lainnya adalah

var temp = [1, 2, 3];
var temp2 = [];
angular.forEach(temp, function(item) {
    this.push(item); //"this" refers to the array passed into the optional third parameter so, in this case, temp2.
}, temp2);

Meskipun, Anda tidak harus melakukan itu, Anda cukup melakukan hal berikut dan itu setara dengan contoh sebelumnya:

angular.forEach(temp, function(item) {
    temp2.push(item);
});

Sekarang ada pro dan kontra dari menggunakan angular.forEachfungsi yang bertentangan dengan forloop bawaan rasa vanilla .

Pro

  • Mudah dibaca
  • Mudah ditulisi
  • Jika tersedia, angular.forEachakan menggunakan loop ES5 forEach. Sekarang, saya akan sampai pada efisiensi di bagian kontra, karena forEach loop jauh lebih lambat daripada for loop. Saya menyebut ini sebagai pro karena senang konsisten dan standar.

Pertimbangkan 2 loop bersarang berikut, yang melakukan hal yang persis sama. Katakanlah kita memiliki 2 array objek dan setiap objek berisi array hasil, yang masing-masing memiliki properti Nilai yang berupa string (atau apa pun). Dan katakanlah kita perlu mengulangi setiap hasil dan jika hasilnya sama maka lakukan beberapa tindakan:

angular.forEach(obj1.results, function(result1) {
    angular.forEach(obj2.results, function(result2) {
        if (result1.Value === result2.Value) {
            //do something
        }
    });
});

//exact same with a for loop
for (var i = 0; i < obj1.results.length; i++) {
    for (var j = 0; j < obj2.results.length; j++) {
        if (obj1.results[i].Value === obj2.results[j].Value) {
            //do something
        }
    }
}

Memang ini adalah contoh hipotetis yang sangat sederhana, tetapi saya telah menulis triple tertanam untuk loop menggunakan pendekatan kedua dan itu sangat sulit dibaca, dan menulis dalam hal ini.

Cons

  • Efisiensi. angular.forEach, dan asli forEach, dalam hal ini, keduanya jauh lebih lambat daripada forloop normal .... sekitar 90% lebih lambat . Jadi untuk set data besar, lebih baik tetap pada forloop asli .
  • Tanpa istirahat, melanjutkan, atau mengembalikan dukungan. continuesebenarnya didukung oleh " kecelakaan ", untuk melanjutkan angular.forEachAnda meletakkan return;pernyataan dalam fungsi seperti angular.forEach(array, function(item) { if (someConditionIsTrue) return; });yang akan menyebabkannya terus keluar dari fungsi untuk iterasi itu. Ini juga disebabkan oleh fakta bahwa penduduk asli forEachtidak mendukung istirahat atau melanjutkan.

Saya yakin ada berbagai pro dan kontra lainnya, dan jangan ragu untuk menambahkan yang Anda inginkan. Saya rasa, intinya, jika Anda membutuhkan efisiensi, tetaplah dengan hanya forloop asli untuk kebutuhan looping Anda. Tetapi, jika set data Anda lebih kecil dan sedikit efisiensi tidak apa-apa untuk menyerah dalam pertukaran untuk keterbacaan dan kemampuan menulis, maka dengan cara apa pun melemparkan angular.forEachanak nakal itu.


34

Jika Anda tidak keberatan mengosongkan array:

var x;

while(x = y.pop()){ 

    alert(x); //do something 

}

xakan berisi nilai terakhir ydan akan dihapus dari array. Anda juga dapat menggunakan shift()yang akan memberi dan menghapus item pertama dari y.


4
Itu tidak berfungsi jika Anda kebetulan memiliki array yang jarang [1, 2, undefined, 3].
M. Grzywaczewski

2
... atau apa pun yang palsu: [1, 2, 0, 3]atau[true, true, false, true]
joeytwiddle

31

Sebuah forEach pelaksanaan ( lihat di jsFiddle ):

function forEach(list,callback) {
  var length = list.length;
  for (var n = 0; n < length; n++) {
    callback.call(list[n]);
  }
}

var myArray = ['hello','world'];

forEach(
  myArray,
  function(){
    alert(this); // do something
  }
);

2
iterator dalam hal ini, sedang melakukan perhitungan panjang yang tidak perlu. Dalam kasus yang ideal, panjang daftar harus dihitung hanya sekali.
MIdhun Krishna

2
@MIdhunKrishna Saya memperbarui jawaban saya dan jsFiddle tetapi perlu diketahui bahwa ini tidak sesederhana yang Anda pikirkan. Lihat pertanyaan
nmoliveira

2
Implementasi lengkap dan benar dapat ditemukan di sini: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
marciowb

29

Mungkin for(i = 0; i < array.length; i++)loop bukan pilihan terbaik. Mengapa? Jika Anda memiliki ini:

var array = new Array();
array[1] = "Hello";
array[7] = "World";
array[11] = "!";

Metode akan memanggil dari array[0]ke array[2]. Pertama, ini pertama akan variabel referensi Anda bahkan tidak memiliki, kedua Anda tidak akan memiliki variabel dalam array, dan ketiga ini akan membuat kode lebih tebal. Lihat di sini, itulah yang saya gunakan:

for(var i in array){
    var el = array[i];
    //If you want 'i' to be INT just put parseInt(i)
    //Do something with el
}

Dan jika Anda ingin itu berfungsi, Anda bisa melakukan ini:

function foreach(array, call){
    for(var i in array){
        call(array[i]);
    }
}

Jika Anda ingin istirahat, sedikit lebih banyak logika:

function foreach(array, call){
    for(var i in array){
        if(call(array[i]) == false){
            break;
        }
    }
}

Contoh:

foreach(array, function(el){
    if(el != "!"){
        console.log(el);
    } else {
        console.log(el+"!!");
    }
});

Ia mengembalikan:

//Hello
//World
//!!!

29

Ada tiga implementasi foreachdi jQuery sebagai berikut.

var a = [3,2];

$(a).each(function(){console.log(this.valueOf())}); //Method 1
$.each(a, function(){console.log(this.valueOf())}); //Method 2
$.each($(a), function(){console.log(this.valueOf())}); //Method 3

2
Log konsol hanya untuk demo. Itu untuk membuatnya menjadi contoh menjalankan cmplete.
Rajesh Paul

29

Pada ECMAScript 6:

list = [0, 1, 2, 3]
for (let obj of list) {
    console.log(obj)
}

Di mana ofmenghindari keanehan yang terkait dengan indan membuatnya bekerja seperti forloop dari bahasa lain, dan letmengikat idalam loop sebagai lawan dalam fungsi.

Kawat gigi ( {}) dapat dihilangkan ketika hanya ada satu perintah (misalnya dalam contoh di atas).


28

Solusi mudah sekarang adalah dengan menggunakan perpustakaan underscore.js . Ini menyediakan banyak alat yang bermanfaat, seperti eachdan akan secara otomatis mendelegasikan pekerjaan kepada penduduk asli forEachjika tersedia.

Contoh CodePen tentang cara kerjanya adalah:

var arr = ["elemA", "elemB", "elemC"];
_.each(arr, function(elem, index, ar)
{
...
});

Lihat juga


23

Tidak ada for eachloop dalam JavaScript asli . Anda dapat menggunakan pustaka untuk mendapatkan fungsi ini (saya sarankan Underscore.js ), gunakan forloop sederhana .

for (var instance in objects) {
   ...
}

Namun, perhatikan bahwa mungkin ada alasan untuk menggunakan forloop yang lebih sederhana (lihat pertanyaan Stack Overflow Mengapa menggunakan "untuk ... dalam" dengan iterasi array, ide yang buruk? )

var instance;
for (var i=0; i < objects.length; i++) {
    var instance = objects[i];
    ...
}

22

Ini adalah iterator untuk daftar NON-jarang di mana indeks dimulai pada 0, yang merupakan skenario khas ketika berhadapan dengan document.getElementsByTagName atau document.querySelectorAll)

function each( fn, data ) {

    if(typeof fn == 'string')
        eval('fn = function(data, i){' + fn + '}');

    for(var i=0, L=this.length; i < L; i++) 
        fn.call( this[i], data, i );   

    return this;
}

Array.prototype.each = each;  

Contoh penggunaan:

Contoh 1

var arr = [];
[1, 2, 3].each( function(a){ a.push( this * this}, arr);
arr = [1, 4, 9]

Contoh # 2

each.call(document.getElementsByTagName('p'), "this.className = data;",'blue');

Setiap tag p mendapat class="blue"

Contoh # 3

each.call(document.getElementsByTagName('p'), 
    "if( i % 2 == 0) this.className = data;",
    'red'
);

Setiap tag p lainnya mendapat class="red">

Contoh # 4

each.call(document.querySelectorAll('p.blue'), 
    function(newClass, i) {
        if( i < 20 )
            this.className = newClass;
    }, 'green'
);

Dan akhirnya 20 tag p biru pertama diubah menjadi hijau

Perhatian saat menggunakan string sebagai fungsi: fungsi ini dibuat di luar konteks dan harus digunakan hanya jika Anda yakin akan pelingkupan variabel. Jika tidak, lebih baik melewati fungsi di mana pelingkupan lebih intuitif.


21

Ada beberapa cara untuk mengulang-ulang array dalam JavaScript, seperti di bawah ini:

untuk - itu yang paling umum . Blok penuh kode untuk perulangan

var languages = ["Java", "JavaScript", "C#", "Python"];
var i, len, text;
for (i = 0, len = languages.length, text = ""; i < len; i++) {
    text += languages[i] + "<br>";
}
document.getElementById("example").innerHTML = text;
<p id="example"></p>

while - loop saat suatu kondisi sedang lewat. Tampaknya menjadi loop tercepat

var text = "";
var i = 0;
while (i < 10) {
    text +=  i + ") something<br>";
    i++;
}
document.getElementById("example").innerHTML = text;
<p id="example"></p>

do / while - juga loop melalui blok kode sementara kondisinya benar, akan berjalan setidaknya satu kali

var text = ""
var i = 0;

do {
    text += i + ") something <br>";
    i++;
}
while (i < 10);

document.getElementById("example").innerHTML = text;
<p id="example"></p>

Loop fungsional - forEach, map, filter, juga reduce(lingkaran mereka melalui fungsi, tetapi mereka digunakan jika Anda perlu untuk melakukan sesuatu dengan array, dll

// For example, in this case we loop through the number and double them up using the map function
var numbers = [65, 44, 12, 4];
document.getElementById("example").innerHTML = numbers.map(function(num){return num * 2});
<p id="example"></p>

Untuk informasi lebih lanjut dan contoh tentang pemrograman fungsional pada array, lihat posting blog Pemrograman fungsional dalam JavaScript: peta, filter dan kurangi .


Koreksi kecil: forEachbukan loop "fungsional" karena tidak mengembalikan yang baru Array(sebenarnya itu tidak mengembalikan apa pun), itu hanya berulang.
nicholaswmin

19

ECMAScript 5 (versi JavaScript) untuk bekerja dengan Array:

forEach - Memisahkan setiap item dalam array dan melakukan apa pun yang Anda butuhkan dengan setiap item.

['C', 'D', 'E'].forEach(function(element, index) {
  console.log(element + " is #" + (index+1) + " in the musical scale");
});

// Output
// C is the #1 in musical scale
// D is the #2 in musical scale
// E is the #3 in musical scale

Dalam hal ini, lebih tertarik pada operasi pada array menggunakan beberapa fitur bawaan.

map - Ini menciptakan array baru dengan hasil dari fungsi callback. Metode ini baik untuk digunakan ketika Anda perlu memformat elemen array Anda.

// Let's upper case the items in the array
['bob', 'joe', 'jen'].map(function(elem) {
  return elem.toUpperCase();
});

// Output: ['BOB', 'JOE', 'JEN']

mengurangi - Seperti namanya, itu mengurangi array ke nilai tunggal dengan memanggil fungsi yang diberikan lewat elemen saat ini dan hasil dari eksekusi sebelumnya.

[1,2,3,4].reduce(function(previous, current) {
  return previous + current;
});
// Output: 10
// 1st iteration: previous=1, current=2 => result=3
// 2nd iteration: previous=3, current=3 => result=6
// 3rd iteration: previous=6, current=4 => result=10

every - Mengembalikan nilai true atau false jika semua elemen dalam array lulus tes dalam fungsi callback.

// Check if everybody has 18 years old of more.
var ages = [30, 43, 18, 5];
ages.every(function(elem) {
  return elem >= 18;
});

// Output: false

filter - Sangat mirip dengan setiap kecuali filter mengembalikan array dengan elemen yang mengembalikan true ke fungsi yang diberikan.

// Finding the even numbers
[1,2,3,4,5,6].filter(function(elem){
  return (elem % 2 == 0)
});

// Output: [2,4,6]

16

Tidak ada kemampuan bawaan untuk masuk forEach. Untuk menghentikan eksekusi, gunakan Array#someseperti di bawah ini:

[1,2,3].some(function(number) {
    return number === 1;
});

Ini berfungsi karena somemengembalikan true segera setelah salah satu dari callback, dieksekusi dalam urutan array, mengembalikan true, hubungan pendek eksekusi sisanya. Jawaban Asli, lihat prototipe array untuk beberapa


13

Saya juga ingin menambahkan ini sebagai komposisi loop terbalik dan jawaban di atas untuk seseorang yang ingin sintaks ini juga.

var foo = [object,object,object];
for (var i = foo.length, item; item = foo[--i];) {
    console.log(item);
}

Pro:

Manfaat untuk ini: Anda sudah memiliki referensi di pertama seperti itu tidak perlu dinyatakan kemudian dengan baris lain. Ini berguna saat perulangan melalui array objek.

Cons:

Ini akan rusak setiap kali referensi salah - falsey (tidak ditentukan, dll.). Ini bisa digunakan sebagai keuntungan. Namun, itu akan membuatnya sedikit lebih sulit untuk dibaca. Dan juga tergantung pada browser itu bisa "tidak" dioptimalkan untuk bekerja lebih cepat daripada yang asli.


12

Cara jQuery menggunakan $.map:

var data = [1, 2, 3, 4, 5, 6, 7];

var newData = $.map(data, function(element) {
    if (element % 2 == 0) {
        return element;
    }
});

// newData = [2, 4, 6];

1
Saya pikir hasilnya lebih mungkin [undefined, 2, undefined, 4, undefined, 6, undefined].

10

Menggunakan loop dengan destruksi ECMAScript 6 dan operator spread

Destrukturisasi dan penggunaan operator penyebaran telah terbukti cukup berguna bagi pendatang baru ke ECMAScript 6 sebagai lebih dapat dibaca / estetika manusia, meskipun beberapa veteran JavaScript mungkin menganggapnya berantakan. Junior atau orang lain mungkin merasa berguna.

Contoh-contoh berikut akan menggunakan for...ofpernyataan dan .forEachmetode.

Contoh 6, 7, dan 8 dapat digunakan dengan loop fungsional seperti .map, .filter, .reduce, .sort, .every, .some. Untuk informasi lebih lanjut tentang metode ini, periksa Array Object .

Contoh 1: Normal for...ofloop - tidak ada trik di sini.

let arrSimple = ['a', 'b', 'c'];

for (let letter of arrSimple) {
  console.log(letter);
}

Contoh 2: Pisahkan kata menjadi karakter

let arrFruits = ['apple', 'orange', 'banana'];

for (let [firstLetter, ...restOfTheWord] of arrFruits) {
  // Create a shallow copy using the spread operator
  let [lastLetter] = [...restOfTheWord].reverse();
  console.log(firstLetter, lastLetter, restOfTheWord);
}

Contoh 3: Looping dengan a keydanvalue

// let arrSimple = ['a', 'b', 'c'];

// Instead of keeping an index in `i` as per example `for(let i = 0 ; i<arrSimple.length;i++)`
// this example will use a multi-dimensional array of the following format type:
// `arrWithIndex: [number, string][]`

let arrWithIndex = [
  [0, 'a'],
  [1, 'b'],
  [2, 'c'],
];

// Same thing can be achieved using `.map` method
// let arrWithIndex = arrSimple.map((i, idx) => [idx, i]);

// Same thing can be achieved using `Object.entries`
// NOTE: `Object.entries` method doesn't work on Internet Explorer  unless it's polyfilled
// let arrWithIndex = Object.entries(arrSimple);

for (let [key, value] of arrWithIndex) {
  console.log(key, value);
}

Contoh 4: Dapatkan properti objek inline

let arrWithObjects = [{
    name: 'Jon',
    age: 32
  },
  {
    name: 'Elise',
    age: 33
  }
];

for (let { name, age: aliasForAge } of arrWithObjects) {
  console.log(name, aliasForAge);
}

Contoh 5: Dapatkan properti objek mendalam dari apa yang Anda butuhkan

let arrWithObjectsWithArr = [{
    name: 'Jon',
    age: 32,
    tags: ['driver', 'chef', 'jogger']
  },
  {
    name: 'Elise',
    age: 33,
    tags: ['best chef', 'singer', 'dancer']
  }
];

for (let { name, tags: [firstItemFromTags, ...restOfTags] } of arrWithObjectsWithArr) {
  console.log(name, firstItemFromTags, restOfTags);
}

Contoh 6: Apakah Contoh 3 digunakan dengan.forEach

let arrWithIndex = [
  [0, 'a'],
  [1, 'b'],
  [2, 'c'],
];

// Not to be confused here, `forEachIndex` is the real index
// `mappedIndex` was created by "another user", so you can't really trust it

arrWithIndex.forEach(([mappedIndex, item], forEachIndex) => {
  console.log(forEachIndex, mappedIndex, item);
});

Contoh 7: Apakah Contoh 4 digunakan dengan.forEach

let arrWithObjects = [{
    name: 'Jon',
    age: 32
  },
  {
    name: 'Elise',
    age: 33
  }
];
// NOTE: Destructuring objects while using shorthand functions
// are required to be surrounded by parentheses
arrWithObjects.forEach( ({ name, age: aliasForAge }) => {
  console.log(name, aliasForAge)
});

Contoh 8: Apakah Contoh 5 digunakan dengan.forEach

let arrWithObjectsWithArr = [{
    name: 'Jon',
    age: 32,
    tags: ['driver', 'chef', 'jogger']
  },
  {
    name: 'Elise',
    age: 33,
    tags: ['best chef', 'singer', 'dancer']
  }
];

arrWithObjectsWithArr.forEach(({
  name,
  tags: [firstItemFromTags, ...restOfTags]
}) => {
  console.log(name, firstItemFromTags, restOfTags);
});


7

Cara terdekat dengan ide Anda adalah dengan menggunakan Array.forEach()yang menerima fungsi penutupan yang akan dieksekusi untuk setiap elemen array.

myArray.forEach(
  (item) => {
    // Do something
    console.log(item);
  }
);

Cara lain yang layak adalah menggunakan Array.map()yang berfungsi dengan cara yang sama, tetapi juga mengambil semua nilai yang Anda kembalikan dan mengembalikannya dalam array baru (pada dasarnya memetakan setiap elemen ke yang baru), seperti ini:

var myArray = [1, 2, 3];
myArray = myArray.map(
  (item) => {
    return item + 1;
  }
);

console.log(myArray); // [2, 3, 4]

1
Ini salah, maptidak mengubah elemen array, karena mengembalikan array baru, dengan item yang baru menjadi hasil penerapan fungsi ke item array lama.
Jesús Franco

Saya tidak pernah mengatakan itu tidak mengembalikan array baru, saya merujuk pada perubahan yang diterapkan oleh fungsi. Tapi di sini saya akan mengubahnya dalam jawabannya.
Ante Jablan Adamović

lagi salah, peta tidak mengubah atau bermutasi di semua item dalam array asli, saya telah mengusulkan dan mengedit jawaban yang menekankan peta bekerja dengan salinan item asli, meninggalkan array asli tidak tersentuh sama sekali
Jesús Franco

7

Anda dapat menghubungi forEach seperti ini:

forEachakan beralih di atas array yang Anda berikan dan untuk setiap iterasi akan memiliki elementyang memegang nilai iterasi itu. Jika Anda membutuhkan indeks, Anda bisa mendapatkan indeks saat ini dengan melewatkan isebagai parameter kedua dalam fungsi panggilan balik untuk forEach.

Foreach pada dasarnya adalah Fungsi Tingkat Tinggi, yang mengambil fungsi lain sebagai parameternya.

let theArray= [1,3,2];

theArray.forEach((element) => {
  // Use the element of the array
  console.log(element)
}

Keluaran:

1
3
2

Anda juga dapat beralih ke array seperti ini:

for (let i=0; i<theArray.length; i++) {
  console.log(i); // i will have the value of each index
}

6

Jika Anda ingin mengulang melalui array objek dengan fungsi panah:

let arr = [{name:'john', age:50}, {name:'clark', age:19}, {name:'mohan', age:26}];

arr.forEach((person)=>{
  console.log('I am ' + person.name + ' and I am ' + person.age + ' old');
})


6

Sintaks lambda biasanya tidak berfungsi di Internet Explorer 10 atau di bawah.

Saya biasanya menggunakan

[].forEach.call(arrayName,function(value,index){
    console.log("value of the looped element" + value);
    console.log("index of the looped element" + index);
});

Jika Anda adalah penggemar jQuery dan sudah menjalankan file jQuery, Anda harus membalik posisi indeks dan parameter nilai

$("#ul>li").each(function(**index, value**){
    console.log("value of the looped element" + value);
    console.log("index of the looped element" + index);
});

5

Jika Anda memiliki array besar yang harus Anda gunakan iteratorsuntuk mendapatkan efisiensi. Iterator adalah properti dari koleksi JavaScript tertentu (sepertiMap , Set, String, Array). Bahkan, for..ofmenggunakan iteratorunder-the-hood.

Iterator meningkatkan efisiensi dengan membiarkan Anda mengonsumsi item dalam daftar satu per satu seolah-olah itu adalah stream. Apa yang membuat iterator spesial adalah bagaimana ia melintasi koleksi. Loop lain perlu memuat seluruh koleksi di depan untuk beralih di atasnya, sedangkan iterator hanya perlu mengetahui posisi saat ini dalam koleksi.

Anda mengakses item saat ini dengan memanggil metode iterator next. Metode selanjutnya akan mengembalikan valueitem saat ini dan booleanuntuk menunjukkan kapan Anda telah mencapai akhir koleksi. Berikut ini adalah contoh membuat iterator dari array.

Ubah array reguler Anda menjadi iterator menggunakan values() metode seperti ini:

    const myArr = [2,3,4]

let it = myArr.values();

console.log(it.next());
console.log(it.next());
console.log(it.next());
console.log(it.next());

Anda juga dapat mengubah array reguler Anda ke iterator menggunakan Symbol.iterator seperti ini:

const myArr = [2,3,4]

let it = myArr[Symbol.iterator]();

console.log(it.next());
console.log(it.next());
console.log(it.next());
console.log(it.next());

Anda juga dapat mengubah reguler Anda arraymenjadi iteratorseperti ini:

let myArr = [8, 10, 12];

function makeIterator(array) {
    var nextIndex = 0;
    
    return {
       next: function() {
           return nextIndex < array.length ?
               {value: array[nextIndex++], done: false} :
               {done: true};
       }
    };
};

var it = makeIterator(myArr);

console.log(it.next().value);   // {value: 8, done: false}
console.log(it.next().value);   // {value: 10, done: false}
console.log(it.next().value);   // {value: 12, done: false}
console.log(it.next().value);   // {value: undefined, done: true}

CATATAN :

  • Iterator bersifat menyeluruh.
  • Objek tidak iterablesecara default. Menggunakanfor..in dalam kasus itu karena alih-alih nilai-nilai itu bekerja dengan kunci.

Anda dapat membaca lebih lanjut tentang di iteration protocol sini .


5

Jika Anda ingin menggunakannya forEach(), akan terlihat seperti -

theArray.forEach ( element => {
    console.log(element);
});

Jika Anda ingin menggunakannya for(), akan terlihat seperti -

for(let idx = 0; idx < theArray.length; idx++){
    let element = theArray[idx];
    console.log(element);
}

4

Sesuai dengan fitur baru yang diperbarui ECMAScript 6 (ES6) dan ECMAScript 2015, Anda dapat menggunakan opsi berikut dengan loop:

untuk loop

for(var i = 0; i < 5; i++){
  console.log(i);
}

// Output: 0,1,2,3,4

untuk ... dalam loop

let obj = {"a":1, "b":2}

for(let k in obj){
  console.log(k)
}

// Output: a,b

Array.forEach ()

let array = [1,2,3,4]

array.forEach((x) => {
  console.log(x);
})

// Output: 1,2,3,4

untuk ... dari loop

let array = [1,2,3,4]

for(let x of array){
  console.log(x);
}

// Output: 1,2,3,4

sementara loop

let x = 0

while(x < 5){
  console.log(x)
  x++
}

// Output: 1,2,3,4

lakukan ... saat loop

let x = 0

do{
  console.log(x)
  x++
}while(x < 5)

// Output: 1,2,3,4

4

Performa

Hari ini (2019-12-18) saya melakukan pengujian pada macOS v10.13.6 (High Sierra), di Chrome v 79.0, Safari v13.0.4 dan Firefox v71.0 (64 bit) - kesimpulan tentang pengoptimalan (dan pengoptimalan mikro yang biasanya tidak layak untuk memperkenalkannya ke kode karena manfaatnya kecil, tetapi kompleksitas kode tumbuh).

  • Sepertinya tradisional for i( Aa ) adalah pilihan yang baik untuk menulis kode cepat di semua browser.

  • Solusi lain, seperti for-of( Iklan ), semua dalam grup C. ... biasanya 2 - 10 (dan lebih) kali lebih lambat dari Aa , tetapi untuk array kecil tidak apa-apa untuk menggunakannya - demi meningkatkan kejelasan kode.

  • Loop dengan panjang array yang di-cache dalam n( Ab, Bb, Be ) terkadang lebih cepat, kadang tidak. Mungkin kompiler secara otomatis mendeteksi situasi ini dan memperkenalkan caching. Perbedaan kecepatan antara versi yang di-cache dan yang tidak di-cache ( Aa, Ba, Bd ) sekitar ~ 1%, jadi sepertinya introduksi nadalah optimasi mikro .

  • The i--seperti solusi mana loop dimulai dari elemen array terakhir ( Ac, Bc ) biasanya ~ 30% lebih lambat dari solusi ke depan - mungkin alasannya adalah cara memory CPU Cache kerja - maju memori membaca lebih optimal untuk CPU caching). Dianjurkan untuk TIDAK MENGGUNAKAN solusi tersebut.

Detail

Dalam pengujian kami menghitung jumlah elemen array. Saya melakukan tes untuk array kecil (10 elemen) dan array besar (elemen 1M) dan membaginya menjadi tiga kelompok:

  • A -for tes
  • B -while tes
  • C - lainnya / metode alternatif

Lintas hasil browser

Hasil untuk semua browser yang diuji

Masukkan deskripsi gambar di sinibrowser **

Array dengan 10 elemen

Hasil untuk Chrome. Anda dapat melakukan tes pada mesin Anda di sini .

Masukkan deskripsi gambar di sini

Array dengan 1.000.000 elemen

Hasil untuk Chrome. Anda dapat melakukan tes pada mesin Anda di sini

Masukkan deskripsi gambar di sini


4

Ringkasan:

Ketika beralih ke array, kita sering ingin mencapai salah satu dari tujuan berikut:

  1. Kami ingin beralih di atas array dan membuat array baru:

    Array.prototype.map

  2. Kami ingin mengulangi array dan tidak membuat array baru:

    Array.prototype.forEach

    for..of lingkaran

Dalam JavaScript, ada banyak cara untuk mencapai kedua tujuan ini. Namun, beberapa lebih nyaman daripada yang lain. Di bawah ini Anda dapat menemukan beberapa metode yang umum digunakan (IMO paling nyaman) untuk menyelesaikan iterasi array dalam JavaScript.

Membuat array baru: Map

map()adalah fungsi yang terletak di Array.prototypemana dapat mengubah setiap elemen array dan kemudian mengembalikan array baru . map()mengambil sebagai argumen fungsi panggilan balik dan bekerja dengan cara berikut:

let arr = [1, 2, 3, 4, 5];

let newArr = arr.map((element, index, array) => {
  return element * 2;
})

console.log(arr);
console.log(newArr);

Callback yang kami sampaikan map()sebagai argumen dieksekusi untuk setiap elemen. Kemudian sebuah array dikembalikan yang memiliki panjang yang sama dengan array asli. Dalam elemen array baru ini ditransformasikan oleh fungsi callback yang diteruskan sebagai argumen map().

Perbedaan yang berbeda antara mapdan mekanisme loop lain seperti forEachdan for..ofloop adalah yang mapmengembalikan array baru dan membiarkan array lama tetap utuh (kecuali jika Anda secara eksplisit memanipulasi dengan berpikir seperti splice).

Juga, perhatikan bahwa mapfungsi callback memberikan nomor indeks dari iterasi saat ini sebagai argumen kedua. Selanjutnya, apakah argumen ketiga menyediakan array yang mapdipanggil? Terkadang sifat ini bisa sangat berguna.

Loop menggunakan forEach

forEachadalah fungsi yang terletak di Array.prototypemana mengambil fungsi callback sebagai argumen. Itu kemudian mengeksekusi fungsi callback ini untuk setiap elemen dalam array. Berbeda dengan map()fungsi, fungsi forEach mengembalikan apa-apa ( undefined). Sebagai contoh:

let arr = [1, 2, 3, 4, 5];

arr.forEach((element, index, array) => {

  console.log(element * 2);

  if (index === 4) {
    console.log(array)
  }
  // index, and oldArray are provided as 2nd and 3th argument by the callback

})

console.log(arr);

Sama seperti mapfungsi, forEachpanggilan balik memberikan nomor indeks dari iterasi saat ini sebagai argumen kedua. Juga, apakah argumen ketiga menyediakan array yang forEachdipanggil?

Loop melalui elemen menggunakan for..of

The for..ofLoop loop melalui setiap elemen array (atau benda iterable lainnya). Ini bekerja dengan cara berikut:

let arr = [1, 2, 3, 4, 5];

for(let element of arr) {
  console.log(element * 2);
}

Dalam contoh di atas, elementsingkatan dari elemen array dan arrmerupakan array yang ingin kita loop. Perhatikan bahwa nama elementtersebut arbitrer, dan kami dapat memilih nama lain seperti 'el' atau sesuatu yang lebih deklaratif saat ini berlaku.

Jangan bingung antara for..inloop dengan for..ofloop. for..inakan mengulang semua properti enumerable dari array sedangkan for..ofloop hanya akan mengulang melalui elemen array. Sebagai contoh:

let arr = [1, 2, 3, 4, 5];

arr.foo = 'foo';

for(let element of arr) {
  console.log(element);
}

for(let element in arr) {
  console.log(element);
}

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.