Ders 12 / 21
Döngüler
Sayaçlı, koşullu ve koleksiyon döngüleri; `for...in` ile `for...of` ayrımı, döngü denetimi, etiketli çıkış ve nesneler üzerinde gezinme.
İçindekiler
Önceki ders tek bir ölçümü sınıflandırdı. Listenin tamamını işlemek için tekrar gerekir. Programlama Temelleri kursundaki Döngüler ve Döngü Denetimi derslerinde bu yapıların amacı ve döngü değişmezi kavramı kurulmuştu; burada JavaScript’in sunduğu biçimler ve aralarındaki — özellikle iki koleksiyon döngüsü arasındaki — fark ele alınıyor.
Dört döngü biçimi vardır ve seçim keyfi değildir: sayaçlı döngü dizin gerektiğinde, koşullu döngü tekrar sayısı önceden bilinmediğinde, koleksiyon döngüleri ise doğrudan elemanlar üzerinde çalışıldığında kullanılır.
Sayaçlı ve Koşullu Döngüler
Klasik for döngüsü üç bölümden oluşur: başlatma, koşul ve tur sonu işlemi. Değişken
Bildirimleri dersinde gösterildiği gibi, sayaç let ile bildirilir ve her turda yeniden
bağlanır.
const sicakliklar = [21.5, 19.75, 23, 18.25]; for (let i = 0; i < sicakliklar.length; i++) { console.log(i, sicakliklar[i]); }
0 21.5 1 19.75 2 23 3 18.25
while döngüsü yalnızca koşul taşır; tekrar sayısı önceden bilinmediğinde kullanılır:
const sicakliklar = [21.5, 19.75, 23, 18.25]; let i = 0; while (i < sicakliklar.length && sicakliklar[i] < 23) { i += 1; } console.log("ilk 23 ve ustu dizin:", i);
ilk 23 ve ustu dizin: 2
Koşuldaki sıra önemlidir. Sınır denetimi (i < sicakliklar.length) önce yazılmıştır;
kısa devre değerlendirme sayesinde dizin aşıldığında ikinci karşılaştırma hiç
yapılmaz. Ters sırada yazılsaydı, dizinin sonunda undefined < 23 karşılaştırması
yapılırdı — bu ifade NaN üreten bir zorlamadan geçtiği için yanlış verir ve döngü yine
biterdi, ama gerekçesi denetim değil rastlantı olurdu.
do...while biçimi gövdeyi en az bir kez çalıştırır; koşul tur sonunda sınanır:
let tur = 0; do { tur += 1; } while (tur < 3); console.log("tur:", tur);
tur: 3
İki Koleksiyon Döngüsü
JavaScript’te birbirine benzeyen iki koleksiyon döngüsü vardır ve farklı şeyler verirler.
for...in, nesnenin sayılabilir özellik anahtarlarını verir. for...of, yinelenebilir
bir değerin elemanlarını verir.
const sicakliklar = [21.5, 19.75, 23]; for (const dizin in sicakliklar) { console.log(typeof dizin, dizin); } for (const deger of sicakliklar) { console.log(typeof deger, deger); }
string 0 string 1 string 2 number 21.5 number 19.75 number 23
İlk döngü dizinleri verdi ve dizinler dizgi tipindedir. Bunun nedeni nesne
anahtarlarının dizgi olmasıdır; dizi de bir nesnedir ve dizinleri anahtar olarak taşır.
Bu, for...in ile toplama yapan kodun neden metin birleştirdiğini açıklar — Tip Dönüşümü
ve Zorlama dersindeki toplama kuralı devreye girer.
Fark, diziye bir özellik eklendiğinde daha da belirginleşir:
const sicakliklar = [21.5, 19.75, 23]; sicakliklar.kaynak = "A1"; for (const dizin in sicakliklar) { console.log("for...in:", dizin); } for (const deger of sicakliklar) { console.log("for...of:", deger); } console.log("length:", sicakliklar.length);
for...in: 0 for...in: 1 for...in: 2 for...in: kaynak for...of: 21.5 for...of: 19.75 for...of: 23 length: 3
for...in dizi elemanı olmayan bir anahtarı da dolaştı; for...of yalnızca elemanları
verdi. length değeri de değişmedi — eklenen özellik dizinin uzunluğuna sayılmaz.
Kursun kuralı buradan çıkar: diziler üzerinde for...of kullanılır. for...in
yalnızca sıradan nesnelerin anahtarlarını dolaşmak için yazılır.
Dizin ile değeri birlikte isteyen durumda ayrı bir yöntem vardır:
const sicakliklar = [21.5, 19.75, 23]; for (const [dizin, deger] of sicakliklar.entries()) { console.log(dizin, deger); }
0 21.5 1 19.75 2 23
Burada dizin sayı tipindedir. Köşeli ayraçlı yazım, çiftin iki bileşenini iki ada ayırır; bu yapıbozum (destructuring) biçimi Diziler ve Nesneler derslerinde ayrıntılı ele alınacak.
Nesneler Üzerinde Gezinme
Sıradan nesneler for...of ile dolaşılamaz:
const kayit = { istasyon: "A1", sicaklik: 21.5, nem: 48 }; try { for (const d of kayit) { console.log(d); } } catch (hata) { console.log(hata.name + ": " + hata.message); }
TypeError: kayit is not iterable
İleti kesindir: nesne yinelenebilir (iterable) değildir. Diziler, dizgiler ve bazı yerleşik koleksiyonlar yinelenebilirdir; sıradan nesneler değildir.
İki yol vardır:
const kayit = { istasyon: "A1", sicaklik: 21.5, nem: 48 }; for (const anahtar in kayit) { console.log(anahtar, kayit[anahtar]); } for (const [anahtar, deger] of Object.entries(kayit)) { console.log(anahtar, "=", deger); }
istasyon A1 sicaklik 21.5 nem 48 istasyon = A1 sicaklik = 21.5 nem = 48
İkisi aynı sonucu verdi, ama kapsamları aynı değil. for...in kalıtılan özellikleri de
dolaşır; Object.entries yalnızca nesnenin kendi özelliklerini verir. Kalıtım zinciri
bir sonraki kursun konusudur; şimdilik ikinci biçimin daha dar ve daha öngörülebilir
olduğunu bilmek yeterlidir. Kursta nesne gezinmesi Object.entries ile yazılacaktır.
Döngü Denetimi
break döngüyü bitirir, continue o turu atlar. İkisi de en içteki döngüye etki eder.
const kayitlar = [ { istasyon: "A1", sicaklik: 21.5 }, { istasyon: "A2", sicaklik: NaN }, { istasyon: "B1", sicaklik: 23 }, { istasyon: "B2", sicaklik: 18.25 }, ]; let toplam = 0; let sayac = 0; for (const kayit of kayitlar) { if (Number.isNaN(kayit.sicaklik)) { continue; } toplam += kayit.sicaklik; sayac += 1; } console.log("gecerli okuma:", sayac, "ortalama:", toplam / sayac); let ilkYuksek = null; for (const kayit of kayitlar) { if (kayit.sicaklik > 22) { ilkYuksek = kayit.istasyon; break; } } console.log("ilk yuksek:", ilkYuksek);
gecerli okuma: 3 ortalama: 20.916666666666668 ilk yuksek: B1
Birinci döngü geçersiz kaydı atladı ve ortalamayı yalnızca geçerli okumalar üzerinden
hesapladı — bölen olarak kayitlar.length yerine sayac kullanılması bu yüzden
zorunludur. İkinci döngü aradığını bulunca durdu; kalan kayıtlara bakılmadı.
Ortalamanın basamakları, İlkel Tipler dersindeki kayan noktalı gösterimin sonucudur:
62.75 / 3 işleminin sonucu ikilik kesir olarak tam yazılamaz ve en yakın temsil
edilebilir değere yuvarlanır.
İç içe döngüde dıştakini kesmek için etiket kullanılır:
const izgara = [[1, 2], [3, 4], [5, 6]]; disDongu: for (const satir of izgara) { for (const hucre of satir) { if (hucre === 4) { console.log("bulundu, iki dongu de kesiliyor"); break disDongu; } console.log("bakilan:", hucre); } }
bakilan: 1 bakilan: 2 bakilan: 3 bulundu, iki dongu de kesiliyor
Etiket, döngünün önüne konan bir addır; break ve continue bu adı alarak hangi döngüye
etki edeceğini belirtir. Etiketsiz break yalnızca iç döngüyü keser ve dış döngü bir
sonraki satıra geçerdi.
Etiketli çıkış seyrek gerekir. Aynı işi bir fonksiyon içine alıp return ile çıkmak
çoğu zaman daha okunaklıdır; fonksiyon tanımı bir sonraki dersin konusudur.
Özet
- Sayaçlı
fordizin gerektiğinde,whiletekrar sayısı bilinmediğinde,do...whilegövdenin en az bir kez çalışması gerektiğinde kullanılır. for...inözellik anahtarlarını verir ve anahtarlar dizgi tipindedir;for...ofelemanları verir.- Dizilerde
for...ofkullanılır;for...indizi olmayan özellikleri de dolaşır. - Sıradan nesneler yinelenebilir değildir; anahtar–değer gezinmesi
Object.entriesile yazılır. breakvecontinueen içteki döngüye etki eder; dıştakine ulaşmak için etiket kullanılır.
Sonraki Adım
Bu derste denetimler ve birikeçler döngü gövdesine gömüldü; aynı işi ikinci kez yapmak gerektiğinde kod kopyalanacaktı. Sonraki ders fonksiyonlara geçiyor ve JavaScript’e özgü bir ayrımla başlıyor: bir fonksiyonu bildirim olarak yazmakla bir ifade olarak yazmak arasındaki fark yalnızca sözdizimi değildir — adın ne zaman erişilebilir olduğunu da belirler.
İlerlemeni kaydetmek ve not almak için Giriş yap
Notlarım
Not almak için giriş yapmalısın.