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

# Yineleyiciler

Yineleme protokolünün iki sözleşmesi, bir türü prototip üzerinden gezilebilir kılmak, yineleyici ile gezilebilir ayrımı, erken çıkışta temizlik ve tembel üretim.

Önceki derste `WeakMap` üzerinde `for...of` denemesi hata verdi, oysa aynı döngü `Map`,
`Set`, dizi ve dizgi üzerinde çalışıyor. Aradaki fark bir tür listesi değildir: `for...of`
döngüsü, yayma işleci, ayrıştırma ve `Array.from` hepsi tek bir sözleşmeye bakar.

**Yineleme protokolü (iteration protocol)** iki sözleşmeden oluşur. Bir nesne
`[Symbol.iterator]` adlı bir yöntem sunuyorsa **gezilebilirdir (iterable)**; bu yöntem,
`next` sunan bir **yineleyici (iterator)** döndürmelidir. Ders önce sözleşmeyi elle kurar,
sonra ölçüm serisini bu sözleşmeye bağlar.

## next Sözleşmesi

Yineleyici, tek bir yöntemi olan sıradan bir nesnedir. `next` çağrısı iki alanlı bir nesne
döndürür: sıradaki değer ve dizinin bitip bitmediği.

```js
function olcumYineleyicisi(degerler) {
  let sira = 0;
  return {
    next() {
      if (sira >= degerler.length) return { value: undefined, done: true };
      const deger = degerler[sira];
      sira += 1;
      return { value: deger, done: false };
    },
  };
}

const yineleyici = olcumYineleyicisi([21.4, 19.8, 25.1]);

console.log(JSON.stringify(yineleyici.next()));
console.log(JSON.stringify(yineleyici.next()));
console.log(JSON.stringify(yineleyici.next()));
console.log(JSON.stringify(yineleyici.next()));

const ikinci = olcumYineleyicisi([21.4, 19.8]);
let adim = ikinci.next();
const toplananlar = [];
while (!adim.done) {
  toplananlar.push(adim.value);
  adim = ikinci.next();
}
console.log(toplananlar.join(","));
console.log(typeof yineleyici[Symbol.iterator]);
```

```
{"value":21.4,"done":false}
{"value":19.8,"done":false}
{"value":25.1,"done":false}
{"done":true}
21.4,19.8
undefined
```

Konum bilgisi `sira` değişkeninde tutulur ve dışarıdan görünmez — Kapanışlar dersindeki
kalıp burada da işler. Dördüncü çıktıda `value` alanının görünmemesi dizileştirmenin
sonucudur: `undefined` değerli alanlar `JSON.stringify` çıktısına girmez.

`while` döngüsü, `for...of` döngüsünün elle yazılmış hâlidir. Son satır ise bu nesnenin
neden `for...of` ile kullanılamayacağını söyler: `next` sunuyor ama `[Symbol.iterator]`
sunmuyor, yani yineleyicidir ama gezilebilir değildir.

## Bir Türü Gezilebilir Kılmak

İkinci sözleşme, bir nesnenin `[Symbol.iterator]` yöntemi sunmasıdır. Yöntem sınıf gövdesine
yazıldığında prototipte durur ve tüm örnekler gezilebilir olur.

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

  [Symbol.iterator]() {
    let sira = 0;
    const degerler = this.degerler;
    return {
      next() {
        if (sira >= degerler.length) return { value: undefined, done: true };
        const deger = degerler[sira];
        sira += 1;
        return { value: deger, done: false };
      },
    };
  }
}

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

const toplananlar = [];
for (const deger of seri) toplananlar.push(deger);
console.log(toplananlar.join(","));

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

const [ilk, ikinci] = seri;
console.log(`${ilk} ${ikinci}`);

console.log(Math.max(...seri));
console.log(Object.hasOwn(seri, Symbol.iterator));
console.log(Object.hasOwn(OlcumSerisi.prototype, Symbol.iterator));
console.log(Object.keys(seri).join(","));
console.log(JSON.stringify(seri));
```

```
21.4,19.8,25.1
21.4,19.8,25.1
3
21.4 19.8
25.1
false
true
sensor,degerler
{"sensor":"S-01","degerler":[21.4,19.8,25.1]}
```

Tek bir yöntem eklendi; beş ayrı dil özelliği çalışır duruma geldi. `for...of`, yayma,
`Array.from`, dizi ayrıştırması ve argüman yayma hepsi aynı sözleşmeyi kullanır.

Altıncı ve yedinci satırlar dersin ekseniyle bağı kurar: yöntem örnekte değil,
`OlcumSerisi.prototype` üzerindedir. Gezilebilirlik nesneye ait bir bayrak değil, zincirde
bulunan bir yöntemdir. Bu yüzden bir türü sonradan gezilebilir kılmak, prototipine bu
yöntemi eklemekle mümkündür.

Simge anahtarlı olduğu için `Object.keys` çıktısında görünmez ve dizileştirmeye girmez;
Özellik Tanımlayıcıları dersinde geçen simge anahtarların bu özelliği, protokol
yöntemlerini veri alanlarından ayrı tutmayı sağlar.

## Yineleyici ile Gezilebilir Ayrımı

İki sözleşme çoğu zaman aynı nesnede birleşir. Yerleşik yineleyiciler kendilerini
döndüren bir `[Symbol.iterator]` yöntemi sunar; bu da onların hem yineleyici hem
gezilebilir olmasını sağlar.

```js
const degerler = [21.4, 19.8, 25.1];

const yineleyici = degerler[Symbol.iterator]();
console.log(typeof yineleyici.next);
console.log(typeof yineleyici[Symbol.iterator]);
console.log(yineleyici[Symbol.iterator]() === yineleyici);

console.log(JSON.stringify(yineleyici.next()));

const kalanlar = [];
for (const deger of yineleyici) kalanlar.push(deger);
console.log(kalanlar.join(","));

const bosDonus = [];
for (const deger of yineleyici) bosDonus.push(deger);
console.log(bosDonus.length);

const birinciTur = [];
for (const deger of degerler) birinciTur.push(deger);
const ikinciTur = [];
for (const deger of degerler) ikinciTur.push(deger);
console.log(birinciTur.length === ikinciTur.length);

const dizgi = "olcum";
console.log([...dizgi].join("-"));
const harita = new Map([["S-01", 21.4]]);
console.log([...harita][0].join("="));
```

```
function
function
true
{"value":21.4,"done":false}
19.8,25.1
0
true
o-l-c-u-m
S-01=21.4
```

Ayrımın pratik sonucu tükenmedir. Yineleyici üzerinde gezinmek onu **tüketir**: ilk
`for...of` kalan iki değeri okur, ikincisi hiçbir şey bulamaz. Gezilebilir nesne ise her
gezinmede yeni bir yineleyici üretir, bu yüzden defalarca gezilebilir.

Bu, bir işleve gezilebilir bir nesne mi yoksa yineleyici mi verildiğinin neden önemli
olduğunu açıklar. İki kez gezmesi gereken bir işleve yineleyici verilirse ikinci geçiş
boş döner; hata mesajı da oluşmaz.

Son iki satır protokolün ne kadar yaygın olduğunu gösterir. Dizgi üzerinde gezinmek kod
birimi değil, kod noktası verir — Bilgisayarlar Nasıl Çalışır kursundaki Karakter
Kodlamaları dersinde tanıtılan ayrım burada gözlenebilir. `Map` üzerinde gezinmek ise
anahtar–değer çiftleri verir.

## Erken Çıkış ve Temizlik

`for...of` döngüsü `break` ile sonlandırıldığında ya da bir hata yükseldiğinde, protokol
yineleyicinin `return` yöntemini çağırır. Bu, açık kalan kaynakların kapatılması için
ayrılmış noktadır.

```js
const kutuk = [];

function kaynakYineleyicisi(degerler) {
  let sira = 0;
  let kapali = false;
  return {
    [Symbol.iterator]() {
      return this;
    },
    next() {
      if (kapali || sira >= degerler.length) return { value: undefined, done: true };
      const deger = degerler[sira];
      sira += 1;
      return { value: deger, done: false };
    },
    return(deger) {
      kapali = true;
      kutuk.push(`kaynak kapatildi, okunan=${sira}`);
      return { value: deger, done: true };
    },
  };
}

const kaynak = kaynakYineleyicisi([21.4, 19.8, 25.1, 18.2]);

for (const deger of kaynak) {
  if (deger > 20 && deger < 22) {
    console.log(`bulundu: ${deger}`);
    break;
  }
}

console.log(kutuk.join(" | "));
console.log(JSON.stringify(kaynak.next()));

const ikinciKaynak = kaynakYineleyicisi([21.4, 19.8]);
const [tekDeger] = ikinciKaynak;
console.log(tekDeger);
console.log(kutuk.length);
```

```
bulundu: 21.4
kaynak kapatildi, okunan=1
{"done":true}
21.4
2
```

`break` deyimi yalnızca döngüyü kırmaz, yineleyiciye de haber verir. Kapatılan yineleyici
sonraki `next` çağrılarında bitmiş olarak yanıt verir. Son bölüm, aynı çağrının dizi
ayrıştırmasında da yapıldığını gösterir: istenen sayıda değer alındıktan sonra kaynak
kapatılır.

Bu davranış, dosya ve ağ akışları gibi kaynaklara bağlı yineleyicilerde önemlidir; erken
çıkış, kaynağın açık kalmasına yol açmaz.

## Tembel Üretim

Protokolün son özelliği, değerlerin **istendikçe** üretilmesidir. Kaynak dizi olsa bile,
her değer üzerinde yapılan hesap yalnızca o değer okunduğunda çalışır.

```js
let hesapSayisi = 0;

function kalibreliSeri(hamDegerler, kayma) {
  return {
    [Symbol.iterator]() {
      let sira = 0;
      return {
        [Symbol.iterator]() {
          return this;
        },
        next() {
          if (sira >= hamDegerler.length) return { value: undefined, done: true };
          hesapSayisi += 1;
          const deger = hamDegerler[sira] + kayma;
          sira += 1;
          return { value: Number(deger.toFixed(2)), done: false };
        },
      };
    },
  };
}

const seri = kalibreliSeri([21.4, 19.8, 25.1, 18.2, 30.0], -0.4);

console.log(hesapSayisi);

let ilkEsikUstu;
for (const deger of seri) {
  if (deger > 24) {
    ilkEsikUstu = deger;
    break;
  }
}

console.log(ilkEsikUstu);
console.log(hesapSayisi);

const hepsi = [...seri];
console.log(hepsi.join(","));
console.log(hesapSayisi);
```

```
0
24.7
3
21,19.4,24.7,17.8,29.6
8
```

Seri kurulduğunda hiçbir hesap yapılmamıştır. Eşiği aşan ilk değer bulunana kadar üç
hesap çalışır; kalan iki değer hiç hesaplanmaz. Aynı seri baştan gezildiğinde beş hesap
daha yapılır ve toplam sekize çıkar.

Aynı iş `map` ile yazılsaydı beş hesap baştan yapılırdı. Programlama Temelleri kursundaki
Fonksiyonel Programlamaya Giriş dersinde tanıtılan **tembel değerlendirme** budur ve
büyük ya da sonu olmayan dizilerde tek uygulanabilir yoldur.

Protokolü elle yazmanın maliyeti de bu örnekte görünür: konum, bitiş koşulu ve kendini
döndüren `[Symbol.iterator]` yöntemi her seferinde tekrarlanır. Sonraki ders bu tekrarı
ortadan kaldıran sözdizimi tanıtacak.

## Özet

- Yineleme protokolü iki sözleşmeden oluşur: gezilebilir nesne `[Symbol.iterator]` sunar,
  yineleyici `next` sunar.
- `for...of`, yayma, ayrıştırma, `Array.from` ve argüman yayma aynı sözleşmeyi kullanır;
  tek bir yöntem eklemek hepsini çalıştırır.
- Sınıf gövdesine yazılan `[Symbol.iterator]` prototipte durur; gezilebilirlik zincirde
  bulunan bir yöntemdir.
- Yineleyici tükenir, gezilebilir nesne her gezinmede yeni yineleyici üretir; iki kez
  gezilmesi gereken yerde bu ayrım belirleyicidir.
- `break` ve erken ayrıştırma, yineleyicinin `return` yöntemini çağırarak kaynak
  temizliğine olanak verir.
- Değerler istendikçe üretilir; okunmayan değer hiç hesaplanmaz.

## Sonraki Adım

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. Dil, bu üçünü de kendisi
üreten bir fonksiyon türü sunar — çalışmasını durdurup kaldığı yerden sürdürebilen
fonksiyonlar. Sonraki ders üreteçleri ele alacak ve bu dersteki tembel seriyi birkaç
satıra indirecek.
