Generator & Iterator — JavaScript

Coba bayangin kasir bank yang panggil antrian: "Nomor 1, ke loket 3." Tunggu nomor 1 selesai dilayani, baru: "Nomor 2, ke loket 3." Kasir gak panggil semua…

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 yield dipanggil next() empat kali. Apa yang didapat dari panggilan keempat? Tebak dulu, jawabannya ada di bagian "next() sampai done: 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 }

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 }

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
}

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

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.

Yang akan kamu pelajari