Materi
for...of, spread, destrukturisasi array, Array.from, dan constructor Map maupun Set menerima objek iterable, yaitu objek yang punya method dengan kunci Symbol.iterator. Method itu mengembalikan iterator: objek dengan method next() yang setiap kali dipanggil memberi objek { value, done }. Selama done bernilai false, value adalah isi berikutnya; begitu done bernilai true, for...of berhenti. Array, string, Map, dan Set sudah iterable. Objek biasa tidak, sehingga for (const x of { a: 1 }) berhenti dengan TypeError yang pesannya diakhiri is not iterable.
Menulis iterator dengan tangan berarti mengurus next dan done sendiri. Generator function, ditulis function* dengan tanda bintang, membuatnya lebih pendek. Memanggilnya belum menjalankan badannya; yang dikembalikan objek generator, yang sekaligus iterator dan iterable. Setiap next() menjalankan badan fungsi sampai yield berikutnya, berhenti di sana, dan memberi nilai yield itu sebagai value. Ketika badan fungsi selesai atau bertemu return, next() memberi done: true; nilai return ikut di objek terakhir itu, sehingga for...of dan spread tidak memakainya. Karena nilainya dibuat satu per satu saat diminta, generator juga bisa mewakili deret tanpa ujung, asalkan pemakainya berhenti sendiri.
function* nomorKursi(baris, jumlah) {
for (let i = 1; i <= jumlah; i++) yield `${baris}${i}`;
}
const g = nomorKursi("C", 2);
g.next(); // { value: "C1", done: false }
g.next(); // { value: "C2", done: false }
g.next(); // { value: undefined, done: true }
[...nomorKursi("D", 3)]; // ["D1", "D2", "D3"]
class Rak {
constructor(...judul) {
this.judul = judul;
}
*[Symbol.iterator]() {
yield* this.judul;
}
}
for (const j of new Rak("Ronggeng", "Atheis")) console.log(j);Di dalam class, method generator ditulis dengan bintang di depan namanya. Method *[Symbol.iterator]() menjadikan setiap objek class itu iterable, sehingga objeknya bisa langsung diputar dengan for...of, dibuka dengan spread, atau dibongkar dengan destrukturisasi array. yield* meneruskan isi iterable lain satu per satu.