Dua Loop, Dua Tugas Berbeda
JavaScript punya dua bentuk loop yang terlihat hampir identik tetapi melakukan hal yang sangat berbeda. for...of menelusuri nilai dari sebuah iterable. for...in menelusuri key dari sebuah objek. Beda satu kata, perilakunya jauh berbeda.
Berikut seluruh ceritanya dalam satu contoh:
Loop pertama mencetak apple, banana, cherry, yaitu nilainya. Loop kedua mencetak 0, 1, 2, yaitu key-nya, sebagai string. Salah pilih, dan kamu akan menghabiskan sepuluh menit bertanya-tanya mengapa array-mu penuh angka.
for...of: Nilai dari Apa Pun yang Iterable
for...of adalah loop yang paling sering akan kamu pakai. Loop ini bekerja pada apa pun yang dianggap iterable oleh JavaScript: array, string, Map, Set, NodeList, generator, dan lainnya.
Tanpa repot mengurus index, tanpa scores[i]. Kamu meminta setiap nilai, kamu mendapat setiap nilai. String juga iterable: for...of menelusurinya karakter demi karakter:
Cara itu juga bekerja dengan benar untuk sebagian besar code point Unicode, keuntungan kecil tetapi nyata dibandingkan mengakses string berdasarkan index angka.
Mendapatkan Index dengan for...of
Satu hal yang tidak langsung diberikan for...of adalah posisinya. Saat kamu membutuhkannya, pasangkan loop dengan entries():
names.entries() menghasilkan pasangan [index, value], dan destructuring di sisi kiri memecahnya menjadi dua variabel. Cara ini biasanya lebih rapi daripada kembali ke for (let i = 0; ...) klasik hanya karena kamu butuh i.
for...in: Key dari Sebuah Objek
for...in dibuat untuk objek biasa. Loop ini melakukan iterasi pada key string yang enumerable:
Perhatikan bahwa yang kamu dapat adalah key, bukan nilainya. Untuk membaca nilainya, kamu mengakses objeknya lagi dengan user[key]. Setiap key adalah string, bahkan kalau terlihat seperti angka.
for...in juga naik melalui rantai prototype, jadi bisa memunculkan property warisan. Untuk literal objek milikmu sendiri, ini jarang jadi masalah, tetapi saat melakukan perulangan pada instance sebuah class atau objek dari library, sebaiknya kamu berjaga-jaga:
Object.hasOwn(user, key) melewati apa pun yang diwariskan. Di kode modern, kebanyakan orang sama sekali menghindari for...in dan memakai Object.keys, Object.values, atau Object.entries, yang membawa kita ke bagian berikutnya.
Cara Modern untuk Perulangan pada Objek
Alih-alih for...in, gabungkan for...of dengan salah satu helper Object.*. Pilih mana di antara ketiganya yang sesuai kebutuhanmu:
Object.entries terutama enak dipakai: destructuring pasangan [key, value] terbaca seperti bahasa sehari-hari. Dan karena method-method ini hanya mengembalikan property enumerable milik objek itu sendiri, kamu tidak perlu khawatir soal property warisan yang tidak diinginkan.
Jangan Pakai for...in pada Array
Secara teknis sah, tetapi sering menjebak orang:
Kamu mendapat 0, 1, 2, dan tag. Property apa pun yang dipasang seseorang ke array itu, atau ke Array.prototype lewat polyfill, juga ikut muncul. Key-nya berupa string, jadi key + 1 menggabungkan teks alih-alih menjumlahkan. Dan urutan iterasinya tidak dijamin sama dengan urutan array di setiap kasus khusus.
Pegangan praktis:
- Nilai array?
for...of arr. - Index dan nilai array?
for...of arr.entries(). - Hanya index array, untuk berhitung?
for (let i = 0; i < arr.length; i++)klasik. - Key atau entri objek?
Object.keys(obj)/Object.entries(obj)denganfor...of.
Intinya: for...in adalah alat untuk kasus khusus. for...of ditambah helper Object sudah mencakup semua yang kamu butuhkan.
break dan continue Berfungsi di Keduanya
Kedua loop mendukung alat keluar lebih awal yang biasa:
continue melompat ke iterasi berikutnya; break keluar dari loop sepenuhnya. Inilah alasan utama untuk lebih memilih for...of daripada .forEach(): callback forEach tidak bisa break keluar dari loop, tetapi for...of bisa.
Ringkasan Berdampingan
Empat loop, empat tugas, satu model mental: kalau kamu ingin nilai dari sesuatu yang iterable, pakai for...of. Kalau kamu ingin bekerja dengan property sebuah objek, lewati Object.keys / Object.values / Object.entries, juga dengan for...of. Sisakan for...in untuk kasus langka saat kamu benar-benar ingin setiap key string yang enumerable dari sebuah objek, warisan atau bukan.
Berikutnya: Truthy dan Falsy
Setiap loop dan if di JavaScript pada akhirnya menanyakan hal yang sama: apakah nilai ini dianggap true? Jawabannya tidak selalu jelas: string kosong, nol, null, dan undefined semuanya berperilaku berbeda dari yang mungkin kamu duga. Nilai truthy dan falsy adalah topik berikutnya.
Pertanyaan yang sering diajukan
Apa bedanya for...of dan for...in di JavaScript?
for...of melakukan iterasi pada nilai dari sebuah iterable seperti array, string, Map, atau Set. for...in melakukan iterasi pada key (nama property) sebuah objek. Untuk array ['a', 'b'], for...of memberimu 'a' dan 'b'; for...in memberimu '0' dan '1' sebagai string.
Bisakah aku memakai for...of pada objek?
Tidak secara langsung, karena objek biasa tidak iterable. Pakai Object.keys(obj), Object.values(obj), atau Object.entries(obj) untuk mendapatkan array yang bisa kamu telusuri dengan for...of. for (const [key, value] of Object.entries(obj)) adalah pola yang umum.
Mengapa sebaiknya tidak memakai for...in pada array?
Secara teknis memang berfungsi, tetapi for...in menelusuri setiap property yang enumerable, termasuk property warisan dan tambahan apa pun yang dipasang seseorang di Array.prototype. Ia juga mengembalikan key sebagai string, dan urutannya tidak selalu terjamin untuk key yang mirip angka di setiap kasus. Pakai for...of untuk nilai, atau loop for klasik saat kamu butuh index-nya.