İçeriğe geç
academia.sh

Ders 10 / 17

Hemen Çağrılan Fonksiyonlar

Fonksiyon bildirimini ifadeye çeviren yazım biçimleri, kapsam yalıtımı ve açığa çıkaran modül kalıbı, tek seferlik kurulum ve blok kapsamıyla karşılaştırma.

İçindekiler

Önceki dersteki döngü tuzağının eski çözümünde bir fonksiyon tanımlanır tanımlanmaz çağrılıyordu. Amacı bir değer üretmek değil, yeni bir kapsam açmaktı. Bu kalıbın adı hemen çağrılan fonksiyon (immediately invoked function expression).

Kalıp iki iş yapar: gövdesindeki bildirimleri dış kapsamdan yalıtır ve içeriden yalnızca seçilen değerleri dışarı verir. Kapanışlar dersindeki fabrika işlevlerinin, tek bir nesne için bir kez çalıştırılan biçimi olarak da okunabilir.

Fonksiyonu İfadeye Çevirmek

Bir deyimin başında function sözcüğü görüldüğünde ayrıştırıcı bunu bir bildirim sayar ve bildirimler hemen çağrılamaz. Kalıbın sarmalayıcı parantezleri bu yüzden vardır: fonksiyonu deyim konumundan çıkarıp ifade konumuna taşırlar.

try {
  new Function("function () { return 1; }();");
} catch (hata) {
  console.log(`bildirim olarak: ${hata.constructor.name}`);
}

const birinci = (function () {
  return "sarmalanan cagri";
})();

const ikinci = (function () {
  return "icerden kapanan";
}());

const ucuncu = (() => "ok bicimi")();

const dorduncu = void (function () {
  console.log("islec ile ifadeye cevrildi");
})();

console.log(birinci);
console.log(ikinci);
console.log(ucuncu);
console.log(dorduncu);
bildirim olarak: SyntaxError
islec ile ifadeye cevrildi
sarmalanan cagri
icerden kapanan
ok bicimi
undefined

İlk deneme, bildirim biçiminin ayrıştırılamadığını gösterir; new Function çağrısı metni ayrıştırdığı için hata çalışma zamanında yakalanabilir. Kalan üç biçim geçerlidir ve aralarında davranış farkı yoktur: çağrı parantezleri sarmalayıcının içinde ya da dışında olabilir, ok fonksiyonu da aynı işi görür.

Dördüncü biçim, bir işleçle ifade konumuna zorlamayı gösterir. void işleci sonucu undefined yaptığı için dönüş değeri kullanılmayan durumlarda tercih edilirdi. Çıktı sırası da bir ayrıntıyı belli eder: gövdedeki yazdırma, console.log(birinci) satırından önce çalışır, çünkü fonksiyon tanımlandığı yerde hemen çağrılır.

Kapsam Yalıtımı ve Modül Kalıbı

Kalıbın asıl kullanımı, bir grup ilişkili işlevi ortak ve gizli bir durum çevresinde toplamaktır. İçeride tanımlananlar dışarıdan görünmez; yalnızca döndürülen nesnedeki adlar erişilebilir olur. Bu kuruluşa açığa çıkaran modül kalıbı (revealing module pattern) denir.

const olcumDefteri = (function () {
  const kayitlar = [];
  let sonrakiSira = 1;

  function ekle(sensor, deger) {
    const kayit = { sira: sonrakiSira, sensor, deger };
    sonrakiSira += 1;
    kayitlar.push(kayit);
    return kayit.sira;
  }

  function sensoreGore(sensor) {
    return kayitlar.filter((k) => k.sensor === sensor).length;
  }

  function ozet() {
    return `${kayitlar.length} kayit, sonraki sira ${sonrakiSira}`;
  }

  return { ekle, sensoreGore, ozet };
})();

console.log(olcumDefteri.ekle("S-01", 21.4));
console.log(olcumDefteri.ekle("S-02", 19.8));
console.log(olcumDefteri.ekle("S-01", 22.0));
console.log(olcumDefteri.sensoreGore("S-01"));
console.log(olcumDefteri.ozet());
console.log(Object.keys(olcumDefteri).join(","));
console.log(typeof olcumDefteri.kayitlar);
console.log(JSON.stringify(olcumDefteri));
1
2
3
2
3 kayit, sonraki sira 4
ekle,sensoreGore,ozet
undefined
{}

Kayıt dizisi ve sıra sayacı dışarıdan erişilemez; defterin arayüzü yalnızca üç işlevden oluşur. Sıra numarasının dışarıdan bozulamaması, Programlama Temelleri kursundaki Nesneye Dayalı Programlamaya Giriş dersinde tanıtılan sınıf değişmezinin korunmasıdır — burada kapsülleme sınıf yerine kapsam sınırıyla sağlanır.

Kalıbın sınıftan ayrıldığı nokta sayıdır: bu kuruluş tek bir nesne üretir. Aynı türden ikinci bir defter isteniyorsa hemen çağırmadan, sıradan bir fabrika işlevi olarak kullanılmalıdır. Tek örnekli yapılar — bir uygulama yapılandırması, bir kütük yazıcısı, bir sayaç — bu kalıbın doğal alanıdır.

Tek Seferlik Kurulum

İkinci yaygın kullanım, bir değeri kurmak için gereken ara adımların dışarı sızmasını önlemektir. Değer bir kez hesaplanır, ara değişkenler kalıbın içinde kalır.

const KALIBRASYON = (function () {
  const hamSatirlar = ["S-01;-0.4", "S-02;0.15", "S-03;0"];
  const tablo = Object.create(null);
  for (const satir of hamSatirlar) {
    const [sensor, kayma] = satir.split(";");
    tablo[sensor] = Number(kayma);
  }
  return Object.freeze(tablo);
})();

console.log(KALIBRASYON["S-01"]);
console.log(KALIBRASYON["S-02"]);
console.log(Object.isFrozen(KALIBRASYON));
console.log(Object.getPrototypeOf(KALIBRASYON));
console.log(typeof hamSatirlar);

try {
  KALIBRASYON["S-04"] = 1;
} catch (hata) {
  console.log(`ekleme: ${hata.constructor.name}`);
}
console.log(Object.keys(KALIBRASYON).join(","));
-0.4
0.15
true
null
undefined
ekleme: TypeError
S-01,S-02,S-03

Ham satırlar ve döngü değişkeni dış kapsamda hiç görünmez; geriye yalnızca kullanıma hazır tablo kalır. Tablo Object.create(null) ile kurulduğu için zinciri yoktur ve Object.freeze ile dondurulduğu için sonradan değiştirilemez — Değişmezlik Teknikleri dersindeki iki karar burada birlikte uygulanmıştır.

Bu kalıp, kurulum maliyeti olan sabitler için uygundur. Kurulumun her kullanımda değil bir kez yapılması, Algoritmalar kursundaki önişleme fikrinin küçük ölçekli bir örneğidir.

Bağımlılığı Dışarıdan Vermek

Kalıbın ikinci yaygın kullanımı, sarmalayıcının parametre listesidir. Dışarıdan kullanılan her ad açıkça geçirilirse, gövde içinde neye bağımlı olunduğu okunur hâle gelir ve ad araması dış kapsamlara çıkmaz.

const ayarlar = { esik: 25 };

const rapor = (function (kaynak, birim) {
  const olcumler = [21.4, 26.8, 23.1];
  const asanlar = olcumler.filter((d) => d > kaynak.esik);
  return `${asanlar.length} olcum ${kaynak.esik}${birim} esigini asti`;
})(ayarlar, "C");

console.log(rapor);

(function kurulumDenetimi() {
  try {
    null.deger;
  } catch (hata) {
    const ilkSatir = hata.stack.split("\n")[1].trim().split(" ")[1];
    console.log("yığıt izindeki ad:", ilkSatir);
  }
})();
1 olcum 25C esigini asti
yığıt izindeki ad: kurulumDenetimi

İkinci çağrı bir ayrıntıyı gösterir: sarmalayıcıya ad verilebilir. Ad dışarıdan erişilebilir değildir — yalnızca fonksiyonun kendi gövdesinde ve yığıt izinde görünür. Adsız bir sarmalayıcıda aynı satır anonim olarak listelenir; hata ayıklarken kalıbın adlandırılmış biçimi tercih edilir.

Yığıt izinin biçimi çalışma zamanına göre değişir; burada yalnızca adın listede yer alması esastır.

Blok Kapsamı ve Modüllerle Karşılaştırma

Kalıbın iki işlevi de dilin sonraki yetenekleriyle büyük ölçüde karşılanır. Blok kapsamlı bildirimler yalıtımı sağlar; modül sistemi dosya düzeyinde ad alanı verir.

let blokSonucu;
{
  const gecici = [21.4, 19.8, 25.1];
  blokSonucu = gecici.length;
}
console.log(blokSonucu);
console.log(typeof gecici);

const ifadeSonucu = (() => {
  const gecici = [21.4, 19.8, 25.1];
  return gecici.reduce((toplam, d) => toplam + d, 0) / gecici.length;
})();
console.log(ifadeSonucu.toFixed(3));

var kapsamDenemesi = "disarida";
(function () {
  var kapsamDenemesi = "iceride";
  console.log(kapsamDenemesi);
})();
console.log(kapsamDenemesi);
3
undefined
22.100
iceride
disarida

Blok, const ve let bildirimlerini yalıtır ve amaç yalnızca yalıtımsa hemen çağrılan fonksiyondan daha yalın bir yoldur. Farkı ikinci bölüm gösterir: blok bir deyimdir, değer üretmez; sonucu dışarı taşımak için önceden bildirilmiş bir değişkene atama gerekir. Hemen çağrılan fonksiyon bir ifadedir ve doğrudan bir sabite bağlanabilir.

Üçüncü bölüm, kalıbın hâlâ gerekli olduğu tek durumu gösterir: var ile bildirilen adlar blok kapsamına girmez, yalnızca fonksiyon kapsamıyla yalıtılır.

Modül sistemi ise ad alanı işlevini devralır. Her dosya kendi kapsamıdır; dışa aktarılmayan hiçbir ad başka dosyadan görülmez. Dosya düzeyinde ad çakışmasını önlemek için kalıba başvurmak gereksizdir. Modül sistemlerinin ayrıntısı Modüller, Araçlar ve Ekosistem kursunun konusudur.

Geriye kalan kullanım alanı üç başlıkta toplanabilir: tek örnekli bir arayüzü gizli durumla birlikte kurmak, bir sabitin kurulum adımlarını yalıtmak ve blok kapsamının yetmediği var bildirimlerini sınırlamak.

Özet

  • Deyim başındaki function sözcüğü bildirim olarak ayrıştırıldığı için, hemen çağrılan fonksiyon bir sarmalayıcıyla ifade konumuna taşınır.
  • Kalıp yeni bir kapsam açar; içeride tanımlananlar dışarıdan görünmez, yalnızca döndürülen değer erişilebilir olur.
  • Açığa çıkaran modül kalıbı, gizli durumu olan tek bir nesne üretir; birden çok örnek gerekiyorsa fabrika işlevi kullanılır.
  • Tek seferlik kurulumda ara değişkenler yalıtılır ve sonuç dondurulmuş bir sabit olarak dışarı verilir.
  • Blok kapsamı yalıtım işlevini karşılar ama değer üretmez; modül sistemi ad alanı işlevini devralır.

Sonraki Adım

Bu konu boyunca fonksiyonlar sürekli değer gibi kullanıldı: geri çağrı olarak aktarıldı, başka bir fonksiyondan döndürüldü, bir nesneye özellik olarak yazıldı, sarmalanarak davranışı değiştirildi. Bu kullanımların hepsi tek bir yetenekten çıkar — fonksiyonun da bir değer olması. Sonraki ders bu yeteneği doğrudan ele alacak ve ölçüm kayıtları üzerinde eşleme, süzme ve indirgeme işlemlerini kurarken bağlanma kurallarının nerede devreye girdiğini gösterecek.

İlerlemeni kaydetmek ve not almak için Giriş yap

Notlarım

Not almak için giriş yapmalısın.

Aramak için yazmaya başlayın.

↑↓ Esc gezin · aç · kapat