Kuasai Protokol Iterator JavaScript. Pelajari cara membuat objek apa pun dapat diiterasi, mengontrol loop `for...of`, dan mengimplementasikan logika iterasi kustom untuk struktur data kompleks dengan contoh praktis.
Mengungkap Iterasi Kustom di JavaScript: Kupas Tuntas Protokol Iterator
Iterasi adalah salah satu konsep paling fundamental dalam pemrograman. Dari memproses item daftar hingga membaca aliran data, kita terus-menerus bekerja dengan urutan informasi. Di JavaScript, kita memiliki alat yang kuat dan elegan seperti loop for...of dan sintaks spread (...) yang membuat iterasi pada tipe bawaan seperti Array, String, dan Map menjadi pengalaman yang mulus.
Tetapi pernahkah Anda berhenti sejenak dan bertanya-tanya apa yang membuat objek-objek ini begitu istimewa? Mengapa Anda bisa menulis for (const char of "hello") tetapi tidak bisa for (const prop of {a: 1, b: 2})? Jawabannya terletak pada sebuah fitur standar ECMAScript yang kuat, namun sering disalahpahami: Protokol Iterator.
Protokol ini bukan hanya mekanisme internal untuk objek bawaan JavaScript. Ini adalah standar terbuka, sebuah kontrak yang dapat diadopsi oleh objek apa pun. Dengan mengimplementasikan protokol ini, Anda dapat mengajarkan JavaScript cara melakukan iterasi pada objek kustom Anda sendiri, menjadikannya warga kelas satu dalam bahasa tersebut. Anda dapat membuka keanggunan sintaksis yang sama dari for...of untuk struktur data kustom Anda, baik itu pohon biner, senarai berantai, urutan giliran dalam permainan, atau linimasa peristiwa.
Dalam panduan komprehensif ini, kita akan mengupas tuntas protokol iterator. Kita akan memecahnya menjadi komponen-komponen intinya, memandu pembuatan iterator kustom dari awal, menjelajahi kasus penggunaan tingkat lanjut seperti urutan tak terbatas, dan akhirnya, menemukan pendekatan modern yang disederhanakan menggunakan fungsi generator. Pada akhirnya, Anda tidak hanya akan memahami cara kerja iterasi di balik layar, tetapi juga diberdayakan untuk menulis kode JavaScript yang lebih ekspresif, dapat digunakan kembali, dan idiomatik.
Inti dari Iterasi: Apa Itu Protokol Iterator JavaScript?
Pertama, penting untuk dipahami bahwa "protokol iterator" bukanlah satu kelas yang Anda perluas atau fungsi spesifik yang Anda panggil. Ini adalah seperangkat aturan atau konvensi yang harus diikuti oleh sebuah objek agar dapat dianggap "iterable" dan untuk menghasilkan sebuah "iterator." Cara terbaik untuk memikirkannya adalah sebagai sebuah kontrak. Jika objek Anda menandatangani kontrak ini, mesin JavaScript berjanji untuk mengetahui cara melakukan loop melaluinya.
Kontrak ini dibagi menjadi dua bagian yang berbeda:
- Protokol Iterable: Ini menentukan apakah sebuah objek dapat diiterasi sejak awal.
- Protokol Iterator: Ini mendefinisikan mekanisme bagaimana objek akan diiterasi, satu nilai pada satu waktu.
Mari kita periksa setiap bagian dari kontrak ini secara detail.
Separuh Pertama Kontrak: Protokol Iterable
Protokol iterable ternyata sangat sederhana. Ia hanya memiliki satu persyaratan:
Sebuah objek dianggap iterable jika ia memiliki properti spesifik yang sudah dikenal luas yang menyediakan metode untuk mengambil sebuah iterator. Properti terkenal ini diakses menggunakan Symbol.iterator.
Jadi, agar sebuah objek menjadi iterable, ia harus memiliki metode yang dapat diakses melalui kunci [Symbol.iterator]. Ketika metode ini dipanggil, ia harus mengembalikan objek iterator (yang akan kita bahas di bagian selanjutnya).
Anda mungkin bertanya, "Apa itu Symbol, dan mengapa tidak menggunakan nama string seperti 'iterator'?" Sebuah Symbol adalah tipe data primitif yang unik dan tidak dapat diubah yang diperkenalkan di ES6. Tujuan utamanya adalah untuk berfungsi sebagai kunci unik untuk properti objek, mencegah tabrakan nama yang tidak disengaja. Jika protokol menggunakan string sederhana seperti 'iterator', kode Anda sendiri mungkin mendefinisikan properti dengan nama yang sama untuk tujuan yang berbeda, yang menyebabkan bug yang tidak terduga. Dengan menggunakan Symbol.iterator, spesifikasi bahasa menjamin kunci yang unik dan terstandarisasi yang tidak akan bentrok dengan kode lain.
Kita dapat dengan mudah memverifikasi ini pada objek iterable bawaan:
const anArray = [1, 2, 3];
const aString = "global";
const aMap = new Map();
console.log(typeof anArray[Symbol.iterator]); // "function"
console.log(typeof aString[Symbol.iterator]); // "function"
console.log(typeof aMap[Symbol.iterator]); // "function"
// Objek biasa tidak iterable secara default
const anObject = { a: 1, b: 2 };
console.log(typeof anObject[Symbol.iterator]); // "undefined"
Separuh Kedua Kontrak: Protokol Iterator
Setelah sebuah objek terbukti iterable dengan menyediakan metode [Symbol.iterator](), fokus beralih ke objek yang dikembalikan oleh metode tersebut: iterator. Iterator adalah pekerja keras yang sesungguhnya; ini adalah objek yang sebenarnya mengelola proses iterasi dan menghasilkan urutan nilai.
Protokol iterator juga sangat lugas. Ia memiliki satu persyaratan:
Sebuah objek adalah iterator jika ia memiliki metode bernama next(). Metode next() ini, ketika dipanggil, harus mengembalikan objek dengan dua properti spesifik:
done(boolean): Properti ini menandakan status iterasi. Nilainyafalsejika masih ada nilai lain dalam urutan. Nilainya menjaditruesetelah iterasi selesai.value(tipe apa pun): Properti ini berisi nilai saat ini dalam urutan. Ketikadonebernilaitrue, propertivaluebersifat opsional dan biasanya berisiundefined.
Mari kita lihat iterator mandiri yang dibuat secara manual untuk melihat cara kerjanya, benar-benar terpisah dari objek iterable apa pun. Iterator ini hanya akan menghitung dari 1 hingga 3.
const manualCounterIterator = {
count: 1,
next: function() {
if (this.count <= 3) {
return { value: this.count++, done: false };
} else {
return { value: undefined, done: true };
}
}
};
// Kita memanggil next() berulang kali untuk mendapatkan setiap nilai
console.log(manualCounterIterator.next()); // { value: 1, done: false }
console.log(manualCounterIterator.next()); // { value: 2, done: false }
console.log(manualCounterIterator.next()); // { value: 3, done: false }
console.log(manualCounterIterator.next()); // { value: undefined, done: true }
console.log(manualCounterIterator.next()); // { value: undefined, done: true } - Tetap dalam keadaan selesai
Inilah mekanisme fundamental yang menggerakkan setiap loop for...of. Ketika Anda menulis for (const item of iterable), mesin JavaScript melakukan hal berikut di balik layar:
- Ia memanggil metode
[Symbol.iterator]()pada objekiterableuntuk mendapatkan sebuah iterator. - Ia kemudian berulang kali memanggil metode
next()pada iterator tersebut. - Untuk setiap objek yang dikembalikan di mana
doneadalahfalse, ia menugaskanvalueke variabel loop Anda (item) dan mengeksekusi badan loop. - Ketika
next()mengembalikan objek di manadoneadalahtrue, loop berakhir.
Membangun dari Awal: Panduan Praktis untuk Iterasi Kustom
Setelah kita memahami teorinya, mari kita terapkan dalam praktik. Kita akan membuat kelas kustom bernama Timeline. Kelas ini akan mengelola kumpulan peristiwa bersejarah, dan tujuan kita adalah membuatnya dapat diiterasi secara langsung, memungkinkan kita untuk melakukan loop melalui peristiwa-peristiwa tersebut dalam urutan kronologis.
Studi Kasus: Kelas Timeline
Kelas Timeline kita akan menyimpan peristiwa, masing-masing berupa objek dengan properti year dan description. Kita ingin dapat menggunakan loop for...of untuk melakukan iterasi melalui peristiwa-peristiwa ini, diurutkan berdasarkan tahun.
class Timeline {
constructor() {
this.events = [];
}
addEvent(year, description) {
this.events.push({ year, description });
}
}
const myTimeline = new Timeline();
myTimeline.addEvent(1995, "JavaScript is created");
myTimeline.addEvent(2009, "Node.js is introduced");
myTimeline.addEvent(1997, "ECMAScript standard is first published");
myTimeline.addEvent(2015, "ES6 (ECMAScript 2015) is released");
// Tujuan: Membuat kode berikut berfungsi
// for (const event of myTimeline) {
// console.log(`${event.year}: ${event.description}`);
// }
Implementasi Langkah-demi-Langkah
Untuk mencapai tujuan kita, kita perlu mengimplementasikan protokol iterator. Ini berarti menambahkan metode [Symbol.iterator]() ke kelas Timeline kita.
Metode ini perlu mengembalikan objek baru—iterator—yang akan berisi metode next() dan mengelola state dari iterasi (misalnya, peristiwa mana yang sedang kita proses). Ini adalah prinsip desain yang krusial bahwa state iterasi harus berada pada iterator, bukan pada objek iterable itu sendiri. Hal ini memungkinkan beberapa iterasi independen pada linimasa yang sama secara bersamaan.
class Timeline {
constructor() {
this.events = [];
}
addEvent(year, description) {
// Kita akan menambahkan pemeriksaan sederhana untuk memastikan integritas data
if (typeof year !== 'number' || typeof description !== 'string') {
throw new Error("Invalid event data");
}
this.events.push({ year, description });
}
// Langkah 1: Implementasikan Protokol Iterable
[Symbol.iterator]() {
// Urutkan peristiwa secara kronologis untuk iterasi.
// Kita membuat salinan agar tidak mengubah urutan array asli.
const sortedEvents = [...this.events].sort((a, b) => a.year - b.year);
let currentIndex = 0;
// Langkah 2: Kembalikan objek iterator
return {
// Langkah 3: Implementasikan Protokol Iterator dengan metode next()
next: () => { // Menggunakan arrow function untuk menangkap `sortedEvents` dan `currentIndex`
if (currentIndex < sortedEvents.length) {
// Masih ada peristiwa lain untuk diiterasi
const currentEvent = sortedEvents[currentIndex];
currentIndex++;
return { value: currentEvent, done: false };
} else {
// Kita telah mencapai akhir dari peristiwa
return { value: undefined, done: true };
}
}
};
}
}
Menyaksikan Keajaiban: Menggunakan Iterable Kustom Kita
Dengan protokol yang diimplementasikan dengan benar, objek Timeline kita sekarang menjadi iterable yang sepenuhnya matang. Ia berintegrasi dengan mulus dengan fitur-fitur bahasa JavaScript yang berbasis iterasi. Mari kita lihat aksinya.
const myTimeline = new Timeline();
myTimeline.addEvent(1995, "JavaScript is created");
myTimeline.addEvent(2009, "Node.js is introduced");
myTimeline.addEvent(1997, "ECMAScript standard is first published");
myTimeline.addEvent(2015, "ES6 (ECMAScript 2015) is released");
console.log("--- Menggunakan loop for...of ---");
for (const event of myTimeline) {
console.log(`${event.year}: ${event.description}`);
}
// Output:
// 1995: JavaScript is created
// 1997: ECMAScript standard is first published
// 2009: Node.js is introduced
// 2015: ES6 (ECMAScript 2015) is released
console.log("\n--- Menggunakan sintaks spread ---");
const eventsArray = [...myTimeline];
console.log(eventsArray);
// Output: Sebuah array dari objek-objek peristiwa, diurutkan berdasarkan tahun
console.log("\n--- Menggunakan Array.from() ---");
const eventsFrom = Array.from(myTimeline);
console.log(eventsFrom);
// Output: Sebuah array dari objek-objek peristiwa, diurutkan berdasarkan tahun
console.log("\n--- Menggunakan destructuring assignment ---");
const [firstEvent, secondEvent] = myTimeline;
console.log(firstEvent);
// Output: { year: 1995, description: 'JavaScript is created' }
console.log(secondEvent);
// Output: { year: 1997, description: 'ECMAScript standard is first published' }
Inilah kekuatan sejati dari protokol ini. Dengan mematuhi kontrak standar, kita telah membuat objek kustom kita kompatibel dengan beragam fitur JavaScript yang ada dan yang akan datang tanpa perlu kerja ekstra.
Meningkatkan Keterampilan Iterasi Anda
Setelah Anda menguasai dasarnya, mari kita jelajahi beberapa konsep yang lebih canggih yang memberi Anda kontrol dan fleksibilitas yang lebih besar.
Pentingnya State dan Iterator Independen
Dalam contoh Timeline kita, kita sangat berhati-hati untuk menempatkan state iterasi (currentIndex dan salinan sortedEvents) di dalam objek iterator yang dikembalikan oleh [Symbol.iterator](). Mengapa ini begitu penting? Karena ini memastikan bahwa setiap kali kita memulai iterasi, kita mendapatkan *iterator baru yang independen*.
Hal ini memungkinkan beberapa konsumen untuk melakukan iterasi pada objek iterable yang sama tanpa mengganggu satu sama lain. Bayangkan jika currentIndex adalah properti dari instance Timeline itu sendiri—itu akan menjadi kekacauan!
const sharedTimeline = new Timeline();
sharedTimeline.addEvent(1, 'Event A');
sharedTimeline.addEvent(2, 'Event B');
sharedTimeline.addEvent(3, 'Event C');
const iterator1 = sharedTimeline[Symbol.iterator]();
const iterator2 = sharedTimeline[Symbol.iterator]();
console.log(iterator1.next().value); // { year: 1, description: 'Event A' }
console.log(iterator2.next().value); // { year: 1, description: 'Event A' } (Memulai iterasinya sendiri)
console.log(iterator1.next().value); // { year: 2, description: 'Event B' } (Tidak terpengaruh oleh iterator2)
Menjadi Tak Terbatas: Membuat Urutan Tanpa Akhir
Protokol iterator tidak mengharuskan sebuah iterasi untuk berakhir. Properti done bisa saja tetap false selamanya. Ini memungkinkan kita untuk memodelkan urutan tak terbatas, yang bisa sangat berguna untuk tugas-tugas seperti menghasilkan ID unik, membuat aliran data acak, atau memodelkan urutan matematis.
Mari kita buat iterator yang menghasilkan urutan Fibonacci tanpa batas.
const fibonacciSequence = {
[Symbol.iterator]() {
let a = 0, b = 1;
return {
next() {
[a, b] = [b, a + b];
return { value: a, done: false };
}
};
}
};
// Kita tidak bisa menggunakan sintaks spread atau Array.from() di sini, karena itu akan menciptakan loop tak terbatas dan menyebabkan crash!
// const fibArray = [...fibonacciSequence]; // BAHAYA: Loop tak terbatas!
// Kita harus mengkonsumsinya dengan hati-hati, menyediakan kondisi penghentian kita sendiri.
console.log("10 angka Fibonacci pertama:");
let count = 0;
for (const number of fibonacciSequence) {
console.log(number);
count++;
if (count >= 10) {
break; // Sangat penting untuk keluar dari loop!
}
}
Metode Iterator Opsional: `return()`
Untuk skenario yang lebih canggih, terutama yang melibatkan manajemen sumber daya (seperti file handle atau koneksi jaringan), sebuah iterator dapat secara opsional memiliki metode return(). Metode ini dipanggil secara otomatis oleh mesin JavaScript jika iterasi dihentikan sebelum waktunya. Ini bisa terjadi jika pernyataan `break`, `return`, atau `throw` keluar dari loop `for...of` sebelum selesai.
Ini memberikan kesempatan pada iterator Anda untuk melakukan tugas-tugas pembersihan.
function createResourceIterator() {
let resourceIsOpen = true;
console.log("Sumber daya dibuka.");
let i = 0;
return {
next() {
if (i < 3) {
return { value: ++i, done: false };
} else {
console.log("Iterator selesai secara alami.");
resourceIsOpen = false;
console.log("Sumber daya ditutup.");
return { done: true };
}
},
return() {
if (resourceIsOpen) {
console.log("Iterator dihentikan lebih awal. Menutup sumber daya.");
resourceIsOpen = false;
}
return { done: true }; // Harus mengembalikan hasil iterator yang valid
}
};
}
console.log("--- Skenario keluar lebih awal ---");
const resourceIterable = { [Symbol.iterator]: createResourceIterator };
for (const value of resourceIterable) {
console.log(`Memproses nilai: ${value}`);
if (value > 1) {
break; // Ini akan memicu metode return()
}
}
Catatan: Ada juga metode throw() untuk propagasi error, tetapi ini utamanya digunakan dalam konteks fungsi generator, yang akan kita bahas selanjutnya.
Pendekatan Modern: Menyederhanakan dengan Fungsi Generator
Seperti yang telah kita lihat, mengimplementasikan protokol iterator secara manual memerlukan manajemen state yang cermat dan kode boilerplate untuk membuat objek iterator dan mengembalikan objek { value, done }. Meskipun penting untuk memahami proses ini, ES6 memperkenalkan solusi yang jauh lebih elegan: fungsi generator.
Fungsi generator adalah jenis fungsi khusus yang dapat dijeda dan dilanjutkan, memungkinkannya menghasilkan urutan nilai dari waktu ke waktu. Ini sangat menyederhanakan pembuatan iterator.
Sintaks kunci:
function*: Tanda bintang mendeklarasikan sebuah fungsi sebagai generator.yield: Kata kunci ini menjeda eksekusi generator dan "menghasilkan" sebuah nilai. Ketika metodenext()dari iterator dipanggil lagi, fungsi akan melanjutkan dari tempat ia berhenti.
Ketika Anda memanggil fungsi generator, ia tidak segera mengeksekusi badannya. Sebaliknya, ia mengembalikan objek iterator yang sepenuhnya sesuai dengan protokol. Mesin JavaScript secara otomatis menangani mesin state, metode next(), dan pembuatan objek { value, done } untuk Anda.
Refactoring Contoh `Timeline` Kita
Mari kita lihat betapa drastisnya fungsi generator dapat menyederhanakan implementasi Timeline kita. Logikanya tetap sama, tetapi kodenya menjadi jauh lebih mudah dibaca dan tidak rentan terhadap kesalahan.
class Timeline {
constructor() {
this.events = [];
}
addEvent(year, description) {
this.events.push({ year, description });
}
// Di-refactor dengan fungsi generator!
*[Symbol.iterator]() { // Tanda bintang menjadikan ini metode generator
// Buat salinan yang diurutkan
const sortedEvents = [...this.events].sort((a, b) => a.year - b.year);
// Lakukan loop melalui peristiwa yang diurutkan
for (const event of sortedEvents) {
// yield menjeda fungsi dan mengembalikan nilai
yield event;
}
// Ketika fungsi selesai, iterator secara otomatis ditandai sebagai 'done'
}
}
// Penggunaannya sama persis, tetapi implementasinya lebih bersih!
const myGenTimeline = new Timeline();
myGenTimeline.addEvent(2002, "The Euro currency is introduced");
myGenTimeline.addEvent(1998, "Google is founded");
for (const event of myGenTimeline) {
console.log(`${event.year}: ${event.description}`);
}
Lihat perbedaannya! Pembuatan objek iterator manual yang kompleks telah hilang. State (peristiwa mana yang sedang kita proses) dikelola secara implisit oleh state jeda dari fungsi generator. Ini adalah cara modern yang lebih disukai untuk mengimplementasikan protokol iterator.
Kekuatan `yield*`
Fungsi generator memiliki kekuatan super lainnya: yield* (yield star). Ini memungkinkan sebuah generator untuk mendelegasikan proses iterasi ke objek iterable lain. Ini adalah alat yang sangat kuat untuk menyusun iterator dari berbagai sumber.
Bayangkan kita memiliki kelas `Project` yang memiliki beberapa objek `Timeline` (misalnya, satu untuk desain, satu untuk pengembangan). Kita dapat membuat `Project` itu sendiri menjadi iterable, dan ia akan dengan mulus melakukan iterasi pada semua peristiwa dari semua linimasanya secara berurutan.
class Project {
constructor(name) {
this.name = name;
this.designTimeline = new Timeline();
this.devTimeline = new Timeline();
}
*[Symbol.iterator]() {
console.log(`Melakukan iterasi melalui peristiwa untuk proyek: ${this.name}`);
console.log("--- Peristiwa Desain ---");
yield* this.designTimeline; // Mendelegasikan ke iterator linimasa desain
console.log("--- Peristiwa Pengembangan ---");
yield* this.devTimeline; // Kemudian mendelegasikan ke iterator linimasa pengembangan
}
}
const websiteProject = new Project("Global Website Relaunch");
websiteProject.designTimeline.addEvent(2023, "Initial wireframes created");
websiteProject.designTimeline.addEvent(2024, "Final brand guide approved");
websiteProject.devTimeline.addEvent(2024, "Backend API developed");
websiteProject.devTimeline.addEvent(2025, "Frontend deployment");
for (const event of websiteProject) {
console.log(` - ${event.year}: ${event.description}`);
}
Gambaran Besar: Mengapa Protokol Iterator adalah Landasan JavaScript Modern
Protokol iterator lebih dari sekadar keingintahuan akademis atau fitur untuk penulis pustaka. Ini adalah pola desain fundamental yang mempromosikan interoperabilitas dan kode yang elegan. Anggap saja sebagai adaptor universal. Dengan membuat objek Anda sesuai dengan standar ini, Anda menghubungkannya ke ekosistem besar fitur bahasa yang dirancang untuk bekerja dengan urutan data apa pun.
Daftar fitur yang mengandalkan protokol iterable sangat luas dan terus bertambah:
- Loop:
for...of - Pembuatan/Penggabungan Array: Sintaks spread (
[...iterable]) danArray.from(iterable) - Struktur Data: Konstruktor untuk
new Map(iterable),new Set(iterable),new WeakMap(iterable), dannew WeakSet(iterable)semua menerima iterable. - Operasi Asinkron:
Promise.all(iterable),Promise.race(iterable), danPromise.any(iterable)beroperasi pada iterable dari Promise. - Destructuring: Anda dapat menggunakan destructuring assignment dengan iterable apa pun:
const [first, second] = myIterable; - API Baru: API modern seperti
Intl.Segmenteruntuk segmentasi teks juga mengembalikan objek iterable.
Ketika Anda membuat struktur data kustom Anda menjadi iterable, Anda tidak hanya mengaktifkan loop for...of; Anda membuatnya kompatibel dengan seluruh rangkaian alat yang kuat ini, memastikan kode Anda kompatibel ke depan dan mudah digunakan serta dipahami oleh developer lain.
Kesimpulan: Langkah Anda Selanjutnya dalam Iterasi
Kita telah melakukan perjalanan dari aturan dasar protokol iterable dan iterator hingga membangun iterator kustom kita sendiri, dan akhirnya ke sintaks fungsi generator yang bersih dan modern. Anda sekarang memiliki pengetahuan untuk mengajarkan JavaScript cara melintasi struktur data apa pun yang dapat Anda bayangkan.
Menguasai protokol ini adalah langkah signifikan dalam perjalanan Anda sebagai developer JavaScript. Ini memindahkan Anda dari menjadi konsumen fitur-fitur bahasa menjadi seorang pencipta yang dapat memperluas kemampuan inti bahasa agar sesuai dengan kebutuhan spesifik Anda.
Wawasan yang Dapat Ditindaklanjuti untuk Developer Global
- Audit Kode Anda: Cari objek dalam proyek Anda saat ini yang mewakili urutan data. Apakah Anda melakukan iterasi pada mereka dengan metode kustom yang tidak standar seperti
.forEachItem()atau.getItems()? Pertimbangkan untuk melakukan refactoring untuk mengimplementasikan protokol iterator standar demi interoperabilitas yang lebih baik. - Manfaatkan Sifat 'Lazy': Gunakan iterator, dan terutama generator, untuk merepresentasikan dataset besar atau bahkan tak terbatas. Ini memungkinkan Anda memproses data sesuai permintaan, yang mengarah pada peningkatan signifikan dalam efisiensi memori dan kinerja. Anda hanya menghitung apa yang Anda butuhkan, saat Anda membutuhkannya.
- Prioritaskan Generator: Untuk setiap objek baru yang Anda buat yang seharusnya dapat diiterasi, jadikan fungsi generator (
function*) sebagai pilihan utama Anda. Mereka lebih ringkas, tidak rentan terhadap kesalahan manajemen state, dan lebih mudah dibaca daripada implementasi manual. - Berpikir dalam Urutan: Mulailah melihat masalah pemrograman melalui lensa urutan. Dapatkah proses bisnis yang kompleks, alur transformasi data, atau transisi state UI dimodelkan sebagai urutan langkah? Jika ya, iterator mungkin menjadi alat yang sempurna dan elegan untuk pekerjaan itu.
Dengan mengintegrasikan protokol iterator ke dalam perangkat pengembangan Anda, Anda akan menulis kode JavaScript yang lebih bersih, lebih kuat, dan lebih idiomatik yang akan dipahami dan dihargai oleh para developer di mana pun di dunia.