Fungsi biasa jalan dari awal sampai selesai dalam sekali panggil. Generator adalah fungsi yang bisa berhenti di tengah jalan, menyerahkan satu nilai, lalu lanjut dari titik itu waktu diminta lagi. Mirip petugas bank yang memanggil nomor antrean satu per satu, bukan semuanya sekaligus.
🧪 Tebakan cepat: generator dengan tiga
yielddipanggilnext()empat kali. Apa yang didapat dari panggilan keempat? Tebak dulu, jawabannya ada di bagian "next()sampaidone: true".
Generator pertama: function* dan yield
function* buah() {
yield 'Apel'
yield 'Mangga'
yield 'Jeruk'
}
const gen = buah()
console.log(gen.next()) // { value: 'Apel', done: false }
console.log(gen.next()) // { value: 'Mangga', done: false }
function*: bintang sesudahfunctionbikin fungsi ini jadi generator. Tanpa bintang,yielddi dalamnya bikin error.yield 'Apel'menyerahkan satu nilai, lalu fungsinya berhenti di situ. Berhenti sementara, bukan selesai.const gen = buah()memanggil generator, tapi body-nya belum jalan sama sekali. Yang kamu dapat adalah objek generator.gen.next()menjalankan body sampaiyieldberikutnya, lalu memberi objek{ value, done }.valueadalah nilai yang di-yield,donemenjawab apakah generatornya sudah habis.
Panggilan pertama sampai di yield 'Apel', panggilan kedua lanjut dari situ dan berhenti di yield 'Mangga'.
next() sampai done: true
Panggil terus, dan sesudah yield terakhir generatornya habis:
const g = buah()
console.log(g.next().value, g.next().value) // Apel Mangga
g.next() // { value: 'Jeruk', done: false }
console.log(g.next()) // { value: undefined, done: true }
.valuemengambil nilainya saja. Tiapnext()maju satuyield, jadi baris kedua mencetakApel Mangga.- Jawaban tebakan: panggilan keempat memberi
{ value: undefined, done: true }. Dipanggil lagi pun hasilnya tetap sama. - Generator yang sudah habis gak bisa diulang. Butuh dari awal lagi? Panggil
buah()sekali lagi buat bikin generator baru.
Ambil semuanya: spread dan for...of
function* hitung(dari, sampai) {
for (let i = dari; i <= sampai; i++) {
yield i
}
}
console.log([...hitung(1, 3)]) // [1, 2, 3]
for (const n of hitung(1, 3)) {
console.log(n) // 1, lalu 2, lalu 3
}
- Generator juga bisa menerima parameter dan memakai loop. Di sini tiap putaran
formenyerahkan satu angka. [...hitung(1, 3)]adalah spread: dia memanggilnext()terus sampaidone: true, lalu mengumpulkan semuavalueke dalam array.for...ofkerjanya sama, tapi memberi nilainya satu per satu ke dalam loop.
Ingat, memanggil generator memberi generator, bukan array. Kalau sebuah fungsi harus mengembalikan array, spread hasil generatornya di dalam fungsi biasa:
function daftar(dari, sampai) {
return [...hitung(dari, sampai)]
}
console.log(daftar(2, 4)) // [2, 3, 4]
Iterator: aturan di balik for...of
Objek yang punya method next() dan memberi { value, done } disebut iterator. for...of dan spread cuma mengandalkan aturan ini. Generator otomatis mengikutinya, begitu juga array dan string:
const it = ['a', 'b'][Symbol.iterator]()
console.log(it.next()) // { value: 'a', done: false }
[Symbol.iterator]() adalah method yang meminta iterator dari sebuah array. Objek yang punya method ini disebut iterable, dan iterable apa pun bisa dipakai di for...of.
⚠️ Jebakan yang sering ketemu
- Lupa bintang.
function buah() { yield 'Apel' }langsung SyntaxError. - Mengira
buah()menjalankan body-nya. Body baru jalan waktunext(), spread, ataufor...ofmeminta nilai. - Memakai generator yang sudah habis. Spread kedua kali dari generator yang sama memberi
[]. Bikin generator baru. - Spread generator tanpa ujung. Generator dengan
while (true)aman dipanggilnext()satu per satu, tapi[...gen]gak pernah selesai dan bikin halaman macet.
TL;DR: Generator ditulis function* dan menyerahkan nilai dengan yield. Memanggilnya memberi objek generator, dan tiap next() jalan sampai yield berikutnya lalu memberi { value, done }. Sesudah yield terakhir hasilnya { value: undefined, done: true }. Spread [...gen] dan for...of mengambil semua nilai sekaligus. Butuh array? return [...generator()] di dalam fungsi biasa. Iterator adalah objek dengan next(), dan generator otomatis jadi iterator.