JavaScript: Başlangıçtan İleri Seviyeye
Bölüm 26 / 313 dk okuma

Iterators ve Generators

Iterable protokolü ve generator fonksiyonlarla lazy değerler üretmek.

Iterable protokolü

Bir obje, [Symbol.iterator]() metodu varsa iterable'dır. Bu metod, her çağrıda { value, done } dönen bir obje verir → bu da iterator'dur.

Array, String, Map, Set zaten iterable. Bu yüzden for...of ile gezilebilirler ve [...x] ile yayılabilirler.

Manuel iterator

const range = {
  start: 1,
  end: 5,
  [Symbol.iterator]() {
    let current = this.start;
    const end = this.end;
    return {
      next() {
        return current <= end
          ? { value: current++, done: false }
          : { value: undefined, done: true };
      },
    };
  },
};
 
for (const n of range) console.log(n); // 1 2 3 4 5
[...range]; // [1, 2, 3, 4, 5]

Generator fonksiyonlar

function* ile tanımlanır. yield ile değer üretir, return'e benzemez: fonksiyonu duraklatır, bir sonraki next()'te kaldığı yerden devam eder.

function* sayilar() {
  yield 1;
  yield 2;
  yield 3;
}
 
const it = sayilar();
it.next();  // { value: 1, done: false }
it.next();  // { value: 2, done: false }
it.next();  // { value: 3, done: false }
it.next();  // { value: undefined, done: true }

Generatorlar otomatik olarak iterable + iterator'dır.

for (const n of sayilar()) console.log(n);
[...sayilar()];  // [1, 2, 3]

Range generator

function* range(start, end, step = 1) {
  for (let i = start; i <= end; i += step) yield i;
}
 
[...range(1, 10)];        // 1..10
[...range(0, 100, 10)];   // 0, 10, 20, ...

Sonsuz dizi

Generator lazy'dir — değer ancak istendiğinde üretilir. Sonsuz dizi güvenle yazılabilir:

function* dogalSayilar() {
  let n = 1;
  while (true) yield n++;
}
 
const it = dogalSayilar();
it.next().value;  // 1
it.next().value;  // 2
it.next().value;  // 3
// ...sonsuz

for...of ile kullanırken break ile çık.

yield* — başka iterable'a delege

function* a() {
  yield 1;
  yield 2;
}
 
function* b() {
  yield 0;
  yield* a();   // a()'nun değerlerini buradan ver
  yield 3;
}
 
[...b()];   // [0, 1, 2, 3]

Pratik: ağaç gezme

function* dolas(node) {
  yield node.value;
  for (const child of node.children ?? []) {
    yield* dolas(child);
  }
}
 
for (const v of dolas(tree)) console.log(v);

Async generator

async function* ile asenkron değerler:

async function* sayfalari() {
  let url = "/api/items?page=1";
  while (url) {
    const res = await fetch(url);
    const data = await res.json();
    yield data.items;
    url = data.nextPage;
  }
}
 
for await (const items of sayfalari()) {
  console.log(items);
}

for await...of ile gezilir. Pagination, stream işleme için ideal.

💬Ne zaman generator?
  • Sonsuz dizi
  • Lazy hesaplama (büyük veri)
  • Stream / async chunk akışı
  • Karmaşık iterable (ağaç gezme, pagination)

Yoksa basit bir dizi [] veya Array.from daha okunaklı.

Bu bölümü bitirdin mi?

İlerlemen tarayıcıda saklanır, eğitim listesinde görünür.

Paylaş