---
title: Üreteçler
source: 'https://academia.sh/tr/kurslar/javascript-nesne-modeli/uretecler'
course: "JavaScript'te Nesneler ve Fonksiyonlar"
language: tr
updated: '2026-08-17T18:09:49+00:00'
license: 'CC BY-SA 4.0'
---

# Üreteçler

Duraklatılabilir fonksiyonlar, üreteç nesnesinin yineleme protokolündeki yeri, sonu olmayan diziler, yetki devri, iki yönlü iletişim ve tembel boru hatları.

Önceki derste elle yazılan yineleyicilerde aynı üç parça sürekli tekrarlandı: konumu tutan
değişken, bitiş koşulu ve kendini döndüren `[Symbol.iterator]` yöntemi. Üçü de mekaniktir
ve fonksiyonun asıl işini gölgeler.

**Üreteç (generator)**, yürütmesini durdurup daha sonra kaldığı yerden sürdürebilen bir
fonksiyondur. `function*` biçiminde tanımlanır ve `yield` deyimiyle bir değer verip durur.
Çağrıldığında gövdesi çalışmaz; protokolün iki sözleşmesini de karşılayan bir nesne
döndürür. Ders bu nesnenin davranışını açar ve önceki dersteki tembel seriyi birkaç
satıra indirir.

## Duraklatılabilir Fonksiyon

Üreteç fonksiyonun gövdesi, ilk `next` çağrısına kadar hiç çalışmaz. Her `next`, bir
sonraki `yield` deyimine kadar ilerler ve orada durur.

```js
let hesapSayisi = 0;

function* kalibreliSeri(hamDegerler, kayma) {
  for (const ham of hamDegerler) {
    hesapSayisi += 1;
    yield Number((ham + kayma).toFixed(2));
  }
}

const uretec = kalibreliSeri([21.4, 19.8, 25.1], -0.4);

console.log(hesapSayisi);
console.log(typeof uretec.next);
console.log(uretec[Symbol.iterator]() === uretec);

console.log(JSON.stringify(uretec.next()));
console.log(hesapSayisi);
console.log(JSON.stringify(uretec.next()));
console.log(JSON.stringify(uretec.next()));
console.log(JSON.stringify(uretec.next()));
console.log(hesapSayisi);

console.log([...kalibreliSeri([21.4, 19.8], -0.4)].join(","));
console.log(typeof kalibreliSeri);
```

```
0
function
true
{"value":21,"done":false}
1
{"value":19.4,"done":false}
{"value":24.7,"done":false}
{"done":true}
3
21,19.4
function
```

İlk satır gövdenin hiç çalışmadığını gösterir. Üçüncü satır üreteç nesnesinin hem
yineleyici hem gezilebilir olduğunu doğrular: kendisini döndüren bir `[Symbol.iterator]`
yöntemi taşır. Önceki derste elle yazılan üç parçanın hepsi burada dilin kendisi
tarafından üretilmiştir.

Beşinci satır tembelliği ölçer: ilk `next` yalnızca bir hesap yapmıştır. Değerler bittiğinde
`done` alanı doğru olur ve `value` alanı `undefined` kalır. Son satır bir ayrımı sabitler —
üreteç fonksiyonun kendisi sıradan bir fonksiyondur; üreteç olan, çağrının döndürdüğü
nesnedir.

Üreteç nesnesi de tükenir. Yeniden gezmek için fonksiyonun tekrar çağrılması gerekir;
onuncu satırdaki yayma bunun için yeni bir üreteç kurar.

## Sınıf Yöntemi Olarak Üreteç

Yöntem adının önüne yıldız konarak sınıf gövdesinde de üreteç tanımlanabilir. Önceki
dersteki `OlcumSerisi` sınıfı böylece yarı yarıya kısalır.

```js
class OlcumSerisi {
  constructor(sensor, degerler, kayma = 0) {
    this.sensor = sensor;
    this.degerler = degerler;
    this.kayma = kayma;
  }

  *[Symbol.iterator]() {
    for (const ham of this.degerler) {
      yield Number((ham + this.kayma).toFixed(2));
    }
  }

  *etiketliCiftler() {
    let sira = 0;
    for (const deger of this) {
      yield [`${this.sensor}#${sira}`, deger];
      sira += 1;
    }
  }
}

const seri = new OlcumSerisi("S-01", [21.4, 19.8, 25.1], -0.4);

console.log([...seri].join(","));
console.log([...seri].join(","));

for (const [etiket, deger] of seri.etiketliCiftler()) {
  console.log(`${etiket} -> ${deger}`);
}

console.log(Object.getOwnPropertyNames(OlcumSerisi.prototype).join(","));
console.log(Object.hasOwn(OlcumSerisi.prototype, Symbol.iterator));
console.log(new Map(seri.etiketliCiftler()).get("S-01#1"));
```

```
21,19.4,24.7
21,19.4,24.7
S-01#0 -> 21
S-01#1 -> 19.4
S-01#2 -> 24.7
constructor,etiketliCiftler
true
19.4
```

Seri iki kez gezilebilir, çünkü gezilen şey serinin kendisidir ve her gezinme yeni bir
üreteç nesnesi üretir. `etiketliCiftler` yöntemi ise `for (const deger of this)` yazarak
kendi sınıfının gezilebilirliğinden yararlanır; ham veriye ikinci kez erişmez.

Yedinci ve sekizinci satırlar zincirle bağı yineler: üreteç yöntemleri de prototipte
durur ve simge anahtarlı olan `Object.keys` çıktısına girmez. Son satır ise protokolün
birleştirici gücünü gösterir — anahtar–değer çiftleri veren herhangi bir gezilebilir
nesne doğrudan `Map` yapıcısına verilebilir.

## Sonu Olmayan Diziler ve Yetki Devri

Üreteç yalnızca istendiğinde çalıştığı için, sonu olmayan bir dizi tanımlamak
sorunsuzdur. `yield*` ise bir üretecin işi başka bir gezilebilir nesneye devretmesini
sağlar.

```js
function* artanZaman(baslangic, adim) {
  let zaman = baslangic;
  while (true) {
    yield zaman;
    zaman += adim;
  }
}

function* ilkN(gezilebilir, adet) {
  if (adet <= 0) return;
  let kalan = adet;
  for (const deger of gezilebilir) {
    yield deger;
    kalan -= 1;
    if (kalan <= 0) return;
  }
}

console.log([...ilkN(artanZaman(1000, 60), 4)].join(","));

function* onSeri() {
  yield 21.4;
  yield 19.8;
}

function* arkaSeri() {
  yield 25.1;
}

function* tumSeri() {
  yield* onSeri();
  yield* arkaSeri();
  yield* [18.2, 30.0];
  return "bitti";
}

const birlesik = tumSeri();
console.log([...tumSeri()].join(","));

let adim = birlesik.next();
const degerler = [];
while (!adim.done) {
  degerler.push(adim.value);
  adim = birlesik.next();
}
console.log(degerler.length);
console.log(adim.value);
```

```
1000,1060,1120,1180
21.4,19.8,25.1,18.2,30
5
bitti
```

`artanZaman` sonsuz bir döngü içerir ama program donmaz: değerler yalnızca istendiğinde
üretilir ve `ilkN` dördüncü değerden sonra durur. Sonsuz döngünün tehlikesiz olması
tembelliğin doğrudan sonucudur; aynı ölçüm zamanlarını bir dizide üretmek imkânsızdır.

`yield*` her tür gezilebilir nesneyi kabul eder — başka bir üreteç ya da sıradan bir dizi.
`return` deyiminin değeri ise `for...of` ve yayma tarafından **atlanır**; yalnızca `next`
çağrısını elle sürdüren kod, bitiş adımının `value` alanında görebilir. Bu yüzden üreteçler
sonuç döndürmek için değil, değer akıtmak için kullanılır.

## İki Yönlü İletişim

`next` çağrısına verilen argüman, üretecin durduğu `yield` ifadesinin değeri olur. Böylece
üreteç yalnızca değer üretmez, dışarıdan değer de alır.

```js
function* esikDenetleyici(baslangicEsigi) {
  let esik = baslangicEsigi;
  const asanlar = [];
  try {
    while (true) {
      const gelen = yield `esik=${esik}, asan=${asanlar.length}`;
      if (typeof gelen === "number") {
        if (gelen > esik) asanlar.push(gelen);
      } else if (typeof gelen === "object" && gelen !== null) {
        esik = gelen.yeniEsik;
      }
    }
  } finally {
    console.log(`kapanis: toplam asan=${asanlar.length}`);
  }
}

const denetleyici = esikDenetleyici(20);

console.log(denetleyici.next("bu deger yok sayilir").value);
console.log(denetleyici.next(21.4).value);
console.log(denetleyici.next(19.8).value);
console.log(denetleyici.next({ yeniEsik: 25 }).value);
console.log(denetleyici.next(25.1).value);
console.log(JSON.stringify(denetleyici.return("elle durduruldu")));
console.log(JSON.stringify(denetleyici.next(30)));
```

```
esik=20, asan=0
esik=20, asan=1
esik=20, asan=1
esik=25, asan=1
esik=25, asan=2
kapanis: toplam asan=2
{"value":"elle durduruldu","done":true}
{"done":true}
```

İlk `next` çağrısının argümanı yok sayılır: gövde henüz hiçbir `yield` ifadesinde durmuş
değildir, dolayısıyla değeri alacak bir yer yoktur. Sonraki çağrılarda gönderilen değer
`gelen` değişkenine düşer.

`return` yöntemi üreteci dışarıdan sonlandırır ve `finally` bloğunu çalıştırır — önceki
dersteki temizlik noktasının üreteçlerdeki karşılığı budur. Sonlanmış bir üreteç sonraki
`next` çağrılarında bitmiş olarak yanıt verir. `throw` yöntemi de benzer biçimde, hatayı
üretecin durduğu noktaya yükseltir.

Kapanışlar dersindeki sayaç ile karşılaştırıldığında fark açıktır: kapanış durumu tutar
ama yürütmeyi tutmaz. Üreteç, durumun yanında **programın nerede kaldığını** da saklar.

## Tembel Boru Hattı

Üreteçlerin en somut kazancı, dönüşüm zincirlerinin ara diziler üretmeden kurulmasıdır.
Süzme ve eşleme birer üreteç olarak yazıldığında, her değer boru hattının tamamından tek
tek geçer.

```js
let okumaSayisi = 0;
let donusumSayisi = 0;

function* hamKaynak(degerler) {
  for (const deger of degerler) {
    okumaSayisi += 1;
    yield deger;
  }
}

function* suz(gezilebilir, olcut) {
  for (const deger of gezilebilir) {
    if (olcut(deger)) yield deger;
  }
}

function* esle(gezilebilir, donusum) {
  for (const deger of gezilebilir) {
    donusumSayisi += 1;
    yield donusum(deger);
  }
}

function* ilkN(gezilebilir, adet) {
  if (adet <= 0) return;
  let kalan = adet;
  for (const deger of gezilebilir) {
    yield deger;
    kalan -= 1;
    if (kalan <= 0) return;
  }
}

const ham = [21.4, 19.8, 25.1, 18.2, 30.0, 27.3, 15.0];
const boruHatti = ilkN(
  esle(
    suz(hamKaynak(ham), (d) => d > 20),
    (d) => Number((d * 1.8 + 32).toFixed(1)),
  ),
  2,
);

console.log(okumaSayisi);
console.log([...boruHatti].join(","));
console.log(okumaSayisi);
console.log(donusumSayisi);

const dizilerle = ham
  .filter((d) => d > 20)
  .map((d) => Number((d * 1.8 + 32).toFixed(1)))
  .slice(0, 2);
console.log(dizilerle.join(","));
```

```
0
70.5,77.2
3
2
70.5,77.2
```

İki yol aynı sonucu verir; yaptıkları iş farklıdır. Üreteçli boru hattı yedi ham değerden
yalnızca üçünü okur ve iki dönüşüm yapar; gerekli olan iki sonuç elde edildiği anda durur.
Dizi yöntemleriyle yazılan sürüm önce beş değeri süzer, beşini de dönüştürür, sonra ilk
ikisini alır — üstelik iki ara dizi üretir.

Fark, veri kaynağı büyüdükçe ya da dönüşüm pahalılaştıkça belirginleşir. Buna karşılık
üreteçli kuruluşun sabit bir maliyeti vardır: her değer için birkaç yürütme geçişi olur.
Küçük dizilerde dizi yöntemleri hem daha kısa hem daha hızlıdır; ölçüt, işlenmeyen
elemanların sayısıdır.

## Özet

- Üreteç fonksiyon çağrıldığında gövdesi çalışmaz; hem yineleyici hem gezilebilir olan bir
  üreteç nesnesi döner.
- Her `next` çağrısı bir sonraki `yield` deyimine kadar ilerler; yürütme orada durur ve
  durum korunur.
- Sınıf gövdesinde yıldızlı yöntem tanımlanabilir; üreteç yöntemleri de prototipte durur.
- `yield*` işi başka bir gezilebilir nesneye devreder; `return` deyiminin değeri yalnızca
  elle sürdürülen `next` çağrılarında görünür.
- `next` argümanı, üretecin durduğu `yield` ifadesinin değeri olur; `return` yöntemi
  `finally` bloğunu çalıştırarak temizlik yapar.
- Üreteçlerden kurulu boru hattı ara dizi üretmez ve yalnızca istenen kadar değer işler.

## Sonraki Adım

Bu konudaki koleksiyonların hepsi keyfi JavaScript değerleri tuttu: sayı, dizgi, nesne.
Bir ölçüm akışını dosyaya yazmak ya da ağ üzerinden aktarmak gerektiğinde ise veri, bayt
dizisi olarak temsil edilmelidir. Sonraki ders sabit boyutlu ikili arabellekleri ve
üzerlerindeki tipli görünümleri ele alacak; bayt sırası ve taşma davranışı da orada
sınanacak.
