Pembaca seperti Anda membantu mendukung MUO. Saat Anda melakukan pembelian menggunakan tautan di situs kami, kami dapat memperoleh komisi afiliasi. Baca selengkapnya.

Mengulangi pengumpulan data menggunakan loop tradisional dapat dengan cepat menjadi rumit dan lambat, terutama saat menangani data dalam jumlah besar.

Generator dan Iterator JavaScript memberikan solusi untuk iterasi yang efisien pada kumpulan data yang besar. Dengan menggunakannya, Anda dapat mengontrol aliran iterasi, menghasilkan nilai satu per satu, dan menjeda serta melanjutkan proses iterasi.

Di sini Anda akan membahas dasar-dasar dan internal iterator JavaScript dan bagaimana Anda dapat membuat iterator secara manual dan menggunakan generator.

Iterator JavaScript

Iterator adalah objek JavaScript yang mengimplementasikan protokol iterator. Benda-benda ini melakukannya dengan memiliki a Berikutnya metode. Metode ini mengembalikan objek yang mengimplementasikan Hasil Iterator antarmuka.

Itu Hasil Iterator antarmuka terdiri dari dua properti:

instagram viewer
Selesai Dan nilai. Itu Selesai properti adalah boolean yang mengembalikan PALSU jika iterator dapat menghasilkan nilai berikutnya dalam urutannya atau BENAR jika iterator telah menyelesaikan urutannya.

Itu nilai properti adalah nilai JavaScript yang dikembalikan oleh iterator selama urutannya. Ketika sebuah iterator menyelesaikan urutannya (kapan SelesaiBENAR), properti ini kembali belum diartikan.

Seperti namanya, iterator memungkinkan Anda untuk "berulang" di atas objek JavaScript seperti array atau peta. Perilaku ini dimungkinkan karena protokol yang dapat diubah.

Dalam JavaScript, protokol iterable adalah cara standar untuk mendefinisikan objek yang dapat Anda ulangi, seperti dalam a untuk... dari lingkaran.

Misalnya:

const buah = ["Pisang", "Buah mangga", "Apel", "Anggur"];

untuk (const iterator dari buah-buahan) {
menghibur.log (iterator);
}

/*
pisang
buah mangga
apel
Anggur
*/

Contoh ini berulang pada buah-buahan susunan menggunakan a untuk... dari lingkaran. Di setiap iterasi, log nilai saat ini ke konsol. Ini dimungkinkan karena array dapat diubah.

Beberapa jenis JavaScript, seperti Array, String, Set, dan Peta, adalah iterable bawaan karena mereka (atau salah satu objek di rantai prototipe mereka) mengimplementasikan sebuah @@iterator metode.

Jenis lain, seperti Objek, tidak dapat diubah secara default.

Misalnya:

const iterObjek = {
mobil: ["Tesla", "BMW", "Toyota"],
hewan: ["Kucing", "Anjing", "hamster"],
makanan: ["Burger", "Pizza", "Semacam spageti"],
};

untuk (const iterator dari iterObject) {
menghibur.log (iterator);
}

// TypeError: iterObject tidak dapat diubah

Contoh ini menunjukkan apa yang terjadi ketika Anda mencoba mengulang objek yang tidak dapat diubah.

Membuat Objek Iterable

Untuk membuat objek iterable, Anda harus mengimplementasikan a Simbol.iterator metode pada objek. Untuk menjadi iterable, metode ini harus mengembalikan objek yang mengimplementasikan Hasil Iterator antarmuka.

Itu Simbol.iterator simbol memiliki tujuan yang sama dengan @@iterator dan dapat digunakan secara bergantian dalam "spesifikasi" tetapi tidak dalam kode sebagai @@iterator bukan sintaks JavaScript yang valid.

Blok kode di bawah ini memberikan contoh cara membuat objek dapat diubah menggunakan iterObject.

Pertama, tambahkan Simbol.iterator metode untuk iterObject menggunakan sebuah fungsi pernyataan.

Seperti itu:

iterObject[Simbol.iterator] = fungsi () {
// Blok kode selanjutnya pergi ke sini...
}

Selanjutnya, Anda harus mengakses semua kunci di objek yang ingin Anda ubah. Anda dapat mengakses kunci menggunakan Objek.kunci metode, yang mengembalikan larik properti enumerable dari suatu objek. Untuk mengembalikan array iterObject' kunci, lulus ini kata kunci sebagai argumen untuk Objek.kunci.

Misalnya:

membiarkan propertiobj = Obyek.kunci(ini)

Akses ke array ini akan memungkinkan Anda untuk menentukan perilaku iterasi objek.

Selanjutnya, Anda perlu melacak iterasi objek. Anda dapat mencapai ini dengan menggunakan variabel penghitung.

Misalnya:

membiarkan indeks properti = 0;
membiarkan indeks anak = 0;

Anda akan menggunakan variabel penghitung pertama untuk melacak properti objek dan yang kedua untuk melacak anak properti.

Selanjutnya, Anda harus menerapkan dan mengembalikan Berikutnya metode.

Seperti itu:

kembali {
Berikutnya() {
// Blok kode selanjutnya pergi ke sini...
}
}

Di dalam Berikutnya metode, Anda harus menangani kasus tepi yang terjadi saat seluruh objek telah diulangi. Untuk menangani kasus tepi, Anda harus mengembalikan objek dengan nilai mulai belum diartikan Dan Selesai mulai BENAR.

Jika kasus ini tidak ditangani, mencoba mengulangi objek akan menghasilkan loop tak terbatas.

Berikut cara menangani kasus tepi:

jika (propertyIndex > propertiobj.panjang- 1) {
kembali {
nilai: belum diartikan,
Selesai: BENAR,
};
}

Selanjutnya, Anda harus mengakses properti objek dan elemen turunannya menggunakan variabel penghitung yang Anda nyatakan sebelumnya.

Seperti itu:

// Mengakses properti induk dan anak
const properti = ini[objProperties[propertyIndex]];

const properti = properti[indeksanak];

Selanjutnya, Anda perlu mengimplementasikan beberapa logika untuk menaikkan variabel penghitung. Logikanya harus mengatur ulang indeksanak ketika tidak ada lagi elemen dalam array properti dan pindah ke properti berikutnya di objek. Selain itu, itu harus meningkat indeksanak, jika masih ada elemen dalam larik properti saat ini.

Misalnya:

// Logika penambahan indeks
if (childIndex >= properti.panjang - 1) {
// jika tidak ada lagi elemen dalam larik anak
// mengatur ulanganakindeks
indeksanak = 0;

// Pindah ke properti berikutnya
propertiIndex++;
} kalau tidak {
// Pindah ke elemen berikutnya dalam larik anak
indeks anak++
}

Akhirnya, kembalikan objek dengan Selesai properti diatur ke PALSU dan nilai properti diatur ke elemen anak saat ini dalam iterasi.

Misalnya:

kembali {
Selesai: PALSU,
nilai: properti,
};

Anda selesai Simbol.iterator fungsinya harus mirip dengan blok kode di bawah ini:

iterObject[Simbol.iterator] = fungsi () {
const propertiobj = Obyek.kunci(ini);
membiarkan indeks properti = 0;
membiarkan indeks anak = 0;

kembali {
Berikutnya: () => {
//Menangani kasus tepi
jika (propertyIndex > propertiobj.panjang- 1) {
kembali {
nilai: belum diartikan,
Selesai: BENAR,
};
}

// Mengakses properti induk dan anak
const properti = ini[objProperties[propertyIndex]];

const properti = properti[indeksanak];

// Logika penambahan indeks
if (childIndex >= properti.panjang - 1) {
// jika tidak ada lagi elemen dalam larik anak
// mengatur ulanganakindeks
indeksanak = 0;

// Pindah ke properti berikutnya
propertiIndex++;
} kalau tidak {
// Pindah ke elemen berikutnya dalam larik anak
indeks anak++
}

kembali {
Selesai: PALSU,
nilai: properti,
};
},
};
};

Menjalankan a untuk... dari putaran iterObject setelah implementasi ini tidak akan menimbulkan kesalahan karena mengimplementasikan a Simbol.iterator metode.

Menerapkan iterator secara manual, seperti yang kami lakukan di atas, tidak disarankan karena sangat rawan kesalahan, dan logikanya mungkin sulit dikelola.

Generator JavaScript

Generator JavaScript adalah fungsi yang dapat Anda jeda dan lanjutkan eksekusi kapan saja. Perilaku ini memungkinkan untuk menghasilkan urutan nilai dari waktu ke waktu.

Fungsi generator, yaitu fungsi yang mengembalikan Generator, menyediakan alternatif untuk membuat iterator.

Anda dapat membuat fungsi generator dengan cara yang sama seperti membuat deklarasi fungsi dalam JavaScript. Satu-satunya perbedaan adalah Anda harus menambahkan tanda bintang (*) ke kata kunci fungsi.

Misalnya:

fungsi* contoh () {
kembali"Generator"
}

Saat Anda memanggil fungsi normal dalam JavaScript, ia mengembalikan nilai yang ditentukan olehnya kembali kata kunci atau belum diartikan jika tidak. Tetapi fungsi generator tidak segera mengembalikan nilai apa pun. Ini mengembalikan objek Generator, yang dapat Anda tetapkan ke variabel.

Untuk mengakses nilai iterator saat ini, panggil Berikutnya metode pada objek Generator.

Misalnya:

const gen = contoh();

console.log (gen.next()); // { nilai: 'Generator', Selesai: BENAR }

Pada contoh di atas, the nilai harta benda berasal dari a kembali kata kunci, menghentikan generator secara efektif. Perilaku ini umumnya tidak diinginkan dengan fungsi generator, karena yang membedakannya dari fungsi normal adalah kemampuan untuk menjeda dan memulai ulang eksekusi.

Kata kunci hasil

Itu menghasilkan kata kunci menyediakan cara untuk mengulangi nilai dalam generator dengan menjeda eksekusi fungsi generator dan mengembalikan nilai yang mengikutinya.

Misalnya:

fungsi* contoh() {
menghasilkan"Model S"
menghasilkan"Model X"
menghasilkan"Truk Cyber"

kembali"Tesla"
}

const gen = contoh();

console.log (gen.next()); // { nilai: 'Model S', Selesai: PALSU }

Pada contoh di atas, ketika Berikutnya metode dipanggil pada contoh generator, itu akan berhenti setiap kali bertemu menghasilkan kata kunci. Itu Selesai properti juga akan diatur ke PALSU sampai bertemu a kembali kata kunci.

Memanggil Berikutnya metode beberapa kali pada contoh generator untuk mendemonstrasikan ini, Anda akan memiliki yang berikut sebagai output Anda.

console.log (gen.next()); // { nilai: 'Model X', Selesai: PALSU }
console.log (gen.next()); // { nilai: 'Truk Dunia Maya', Selesai: PALSU }
console.log (gen.next()); // { nilai: 'Tesla', Selesai: BENAR }

menghibur.log (gen.next()); // { nilai: tidak terdefinisi, selesai: benar }

Anda juga dapat mengulangi objek Generator menggunakan untuk... dari lingkaran.

Misalnya:

untuk (const iterator dari gen) {
menghibur.log (iterator);
}

/*
Model S
Model X
Truk Cyber
*/

Menggunakan Iterator dan Generator

Meskipun iterator dan generator mungkin tampak seperti konsep abstrak, sebenarnya tidak. Mereka dapat membantu saat bekerja dengan aliran data dan pengumpulan data tanpa batas. Anda juga dapat menggunakannya untuk membuat pengidentifikasi unik. Pustaka manajemen negara bagian seperti MobX-State-Tree (MST) juga menggunakannya di bawah tenda.