Takip et

JavaScript Nasıl Çalışır? Bölüm 2: Yürütme Bağlamı ve Çağrı Yığınına Derin Bir Bakış

JavaScript Nasıl Çalışır? Bölüm 2: Yürütme Bağlamı ve Çağrı Yığınına Derin Bir Bakış JavaScript’in büyüleyici dünyasında derinlere inmeye hazır mısınız?

JavaScript Nasıl Çalışır? Bölüm 2: Yürütme Bağlamı ve Çağrı Yığınına Derin Bir Bakış

JavaScript’in büyüleyici dünyasında derinlere inmeye hazır mısınız? Bu makale serimizin ikinci bölümünde, JavaScript kodunuzun sahne arkasında nasıl işlediğini anlamak için iki temel yapı taşını inceleyeceğiz: Yürütme Bağlamı (Execution Context) ve Çağrı Yığını (Call Stack). Bu kavramlar, değişkenlerin nasıl erişilebilir olduğunu, fonksiyonların nasıl çağrıldığını ve kodunuzun hangi sırayla çalıştığını belirler. JavaScript’in bu temel mekanizmalarını kavradığınızda, daha temiz, daha verimli ve hatasız kod yazma yeteneğiniz önemli ölçüde gelişecektir. Gelin, bu karmaşık görünen ama aslında oldukça mantıklı yapıları basit bir dille açıklayalım.

Yürütme Bağlamı (Execution Context) Nedir?

JavaScript motoru bir kod parçasını çalıştırdığında, o kod için özel bir ortam oluşturur. Bu ortama “Yürütme Bağlamı” denir. Her fonksiyon çağrısı, her modül ve hatta global kapsam bile kendi yürütme bağlamına sahiptir. Bu bağlam, kodun çalıştırılması için gerekli tüm bilgileri (değişkenler, fonksiyonlar, this anahtar kelimesinin değeri gibi) barındıran soyut bir yapıdır. JavaScript tek iş parçacıklı (single-threaded) bir dil olduğu için, aynı anda yalnızca bir yürütme bağlamı aktif olabilir.

Tanım ve Önemi

Yürütme bağlamı, JavaScript kodunun çalıştırıldığı sanal bir kapsayıcı veya “çalışma alanı” olarak düşünülebilir. Her yürütme bağlamı iki ana aşamadan geçer:

1. Oluşturma Aşaması (Creation Phase): Bu aşamada, motor kodu tarar ve değişkenler ile fonksiyon bildirimleri için hafızada yer ayırır (hoisting). Ayrıca this anahtar kelimesinin değerini belirler ve Lexical Ortamı ile Değişken Ortamını oluşturur.
2. Yürütme Aşaması (Execution Phase): Bu aşamada ise kod satır satır çalıştırılır, değişkenlere değerler atanır ve fonksiyonlar çağrılır.

Yürütme bağlamını anlamak, değişkenlerin kapsamını (scope), this anahtar kelimesinin davranışını ve hata ayıklama süreçlerini kavramak için hayati öneme sahiptir.

Yürütme Bağlamı Türleri

JavaScript’te üç ana yürütme bağlamı türü bulunur:

1. Global Yürütme Bağlamı (Global Execution Context – GEC):
* Bir JavaScript dosyası ilk yüklendiğinde veya bir tarayıcı sekmesi açıldığında oluşan ilk bağlamdır.
* Tüm global değişkenler ve fonksiyonlar burada tanımlanır.
* Tarayıcı ortamında window nesnesini, Node.js ortamında ise global nesnesini this olarak bağlar.
* Her zaman yalnızca bir global yürütme bağlamı vardır.
2. Fonksiyon Yürütme Bağlamı (Function Execution Context – FEC):
* Bir fonksiyon her çağrıldığında yeni bir fonksiyon yürütme bağlamı oluşturulur.
* Her fonksiyonun kendi değişken ortamı, lexical ortamı ve this bağlamı vardır.
* Fonksiyon çalışması bittiğinde, bu bağlam çağrı yığınından kaldırılır.
3. Eval Yürütme Bağlamı (Eval Execution Context):
* eval() fonksiyonu kullanılarak çalıştırılan kod için oluşturulur.
* Kullanımı genellikle önerilmez çünkü güvenlik açıkları oluşturabilir ve performansı düşürebilir.

Yürütme Bağlamının Bileşenleri

Her yürütme bağlamı, içindeki kodun nasıl çalıştığını belirleyen üç ana bileşene sahiptir:

1. Değişken Ortamı (Variable Environment):
* Bu, var ile tanımlanmış değişkenleri ve fonksiyon bildirimlerini içerir.
* Oluşturma aşamasında, bu değişkenler undefined olarak başlatılır ve fonksiyon bildirimleri tamamen hafızaya alınır (hoisting).
2. Lexical Ortam (Lexical Environment):
* Bu, değişkenlerin ve fonksiyonların tanımlandığı fiziksel konuma göre kapsamlarını belirler.
* let ve const ile tanımlanmış değişkenler burada tutulur. var değişkenleri de burada bulunur ancak davranışları Değişken Ortamındaki var‘dan farklıdır (hoisting).
* Bir dış Lexical Ortama (outer lexical environment) referans içerir, bu da kapsam zincirini (scope chain) oluşturur.
3. this Bağlamı (This Binding):
* this anahtar kelimesinin değerini belirler. Bu değer, fonksiyonun nasıl çağrıldığına bağlı olarak değişir.

Yürütme Bağlamının Bileşenleri Detaylı İncelendi

Yürütme bağlamının üç temel bileşenini daha yakından inceleyelim. Bu bileşenler, JavaScript’in dinamik doğasını anlamak için kritik öneme sahiptir.

Değişken Ortamı (Variable Environment)

Değişken Ortamı, bir yürütme bağlamının oluşturma aşamasında ilk olarak doldurulan kısımdır. Temel olarak, var anahtar kelimesiyle tanımlanmış tüm değişkenleri ve function anahtar kelimesiyle tanımlanmış tüm fonksiyon bildirimlerini barındırır. Bu bileşenin en dikkat çekici özelliği, “hoisting” (yukarı çekme) mekanizmasını desteklemesidir.

* Hoisting: JavaScript motoru kodu çalıştırmadan önce, tüm var değişken bildirimlerini ve fonksiyon bildirimlerini mevcut kapsamın en üstüne taşır. var değişkenleri undefined değeriyle başlatılırken, fonksiyon bildirimleri tamamen hafızaya alınır ve doğrudan çağrılabilir hale gelir.

console.log(a); // undefined (hoisted, ama değeri atanmadı)
var a = 10;
console.log(a); // 10

selamVer(); // Merhaba Dünya!
function selamVer() {
  console.log("Merhaba Dünya!");
}
// merhaba(); // Hata: merhaba is not a function (fonksiyon ifadesi hoisted olmaz)
var merhaba = function() {
  console.log("Merhaba");
};

Bu örnekte, a değişkeni tanımlanmadan önce erişilebilmiş, ancak undefined değeriyle. selamVer fonksiyonu ise tanımlanmadan önce bile çağrılabilmiştir. Bu, Değişken Ortamının oluşturma aşamasındaki rolünü gösterir.

Lexical Ortam (Lexical Environment)

Lexical Ortam, bir yürütme bağlamının diğer önemli bileşenidir ve değişkenlerin ve fonksiyonların fiziksel olarak kodda nerede yazıldığına göre kapsamlarını (scope) belirler. Bu, özellikle let ve const anahtar kelimeleriyle tanımlanan değişkenler için geçerlidir ve blok kapsamı (block scope) kavramını getirir.

* Kapsam Zinciri (Scope Chain): Her Lexical Ortam, kendisini çevreleyen (dış) Lexical Ortama bir referans içerir. Bu referanslar zinciri, bir değişkenin veya fonksiyonun belirli bir kapsamda bulunamadığında, JavaScript motorunun dış kapsamlara doğru arama yapmasını sağlar. Bu zincir, global Lexical Ortama kadar devam eder.
* let ve const: Bu anahtar kelimelerle tanımlanan değişkenler, var gibi hoisting'e uğramazlar ve tanımlandıkları blok içinde geçerlidirler. Tanımlanmadan önce erişilmeye çalışıldığında "Temporal Dead Zone (TDZ)" hatası verirler.

let globalDegisken = "Ben globalim";

function disFonksiyon() {
  let disDegisken = "Ben dış fonksiyonum";

  function icFonksiyon() {
    let icDegisken = "Ben iç fonksiyonum";
    console.log(icDegisken); // "Ben iç fonksiyonum"
    console.log(disDegisken); // "Ben dış fonksiyonum" (dış Lexical Ortamdan erişildi)
    console.log(globalDegisken); // "Ben globalim" (global Lexical Ortamdan erişildi)
  }
  icFonksiyon();
  // console.log(icDegisken); // Hata: icDegisken is not defined (dış kapsamdan erişilemez)
}
disFonksiyon();

Bu örnekte, icFonksiyon kendi kapsamında icDegisken'i bulamazsa, bir üst Lexical Ortama (disFonksiyon'un Lexical Ortamı) bakar ve disDegisken'i bulur. Eğer orada da bulamazsa, bir üst Lexical Ortama (global Lexical Ortam) bakar ve globalDegisken'i bulur. Bu, kapsam zincirinin nasıl çalıştığını gösterir.

this Anahtar Kelimesi ve Bağlamı

this anahtar kelimesi, JavaScript'teki en kafa karıştırıcı konulardan biri olabilir çünkü değeri, fonksiyonun nasıl çağrıldığına bağlı olarak dinamik olarak değişir. this bağlamı, bir fonksiyonun yürütme bağlamında this'in hangi nesneye referans ettiğini belirler.

* Global Bağlam: Global yürütme bağlamında this, tarayıcıda window nesnesine, Node.js'te ise global nesnesine referans eder.
* Fonksiyon Bağlamı (Normal Fonksiyonlar):
* Varsayılan Bağlama: Sıkı modda ('use strict') olmayan basit bir fonksiyon çağrısında this, global nesneye (window veya global) referans eder. Sıkı modda ise undefined olur.
* İmplicit Bağlama (Metot Çağrısı): Bir fonksiyon bir nesnenin metodu olarak çağrıldığında, this o nesneye referans eder.
* Explicit Bağlama (call, apply, bind): Bu metotlar kullanılarak this'in değeri açıkça belirlenebilir.
* new Bağlama: Bir kurucu fonksiyon new anahtar kelimesiyle çağrıldığında, this yeni oluşturulan nesneye referans eder.
* Arrow Fonksiyonlar: Arrow fonksiyonlar kendi this bağlamlarına sahip değildir. this değerini, tanımlandıkları Lexical Ortamdan (yani çevreleyen kapsamdan) miras alırlar.

// Global bağlam
console.log(this === window); // Tarayıcıda: true

const nesne = {
  ad: "Ali",
  selamla: function() {
    console.log("Merhaba, ben " + this.ad);
  },
  selamlaArrow: () => {
    console.log("Merhaba, ben " + this.ad); // Global 'this'e referans eder
  }
};

nesne.selamla(); // Merhaba, ben Ali (this = nesne)
nesne.selamlaArrow(); // Merhaba, ben undefined (this = window, window.ad undefined)

const selamlaFonksiyonu = nesne.selamla;
selamlaFonksiyonu(); // Merhaba, ben undefined (this = window, varsayılan bağlama)

const baskaNesne = { ad: "Veli" };
nesne.selamla.call(baskaNesne); // Merhaba, ben Veli (explicit bağlama)

Bu karmaşık this davranışını anlamak, özellikle nesne yönelimli JavaScript ve event handler'lar ile çalışırken büyük önem taşır.

Çağrı Yığını (Call Stack) Nedir ve Nasıl Çalışır?

JavaScript motoru tek iş parçacıklı (single-threaded) olduğu için, bir seferde yalnızca bir işlem yapabilir. Bu işlemlerin sırasını yöneten mekanizma ise Çağrı Yığını'dır (Call Stack). Çağrı Yığını, bir programdaki fonksiyon çağrılarını izleyen ve hangi fonksiyonun şu anda yürütülmekte olduğunu belirleyen bir veri yapısıdır.

Tanım ve LIFO Prensibi

Çağrı Yığını, "Son Giren İlk Çıkar" (Last In, First Out - LIFO) prensibine göre çalışan soyut bir veri yapısıdır. Bir yığın gibi düşünebilirsiniz: en son eklenen öğe, yığından ilk çıkarılan öğe olacaktır.

* Push (Ekleme): Bir fonksiyon çağrıldığında, o fonksiyona ait yeni bir yürütme bağlamı oluşturulur ve Çağrı Yığını'nın en üstüne eklenir (push).
* Pop (Çıkarma): Bir fonksiyonun yürütülmesi tamamlandığında (yani return ifadesine ulaşıldığında veya bir hata fırlatıldığında), o fonksiyona ait yürütme bağlamı Çağrı Yığını'nın en üstünden kaldırılır (pop).

Yürütme Bağlamlarının Yığına Eklenmesi ve Çıkarılması

JavaScript motoru, kodu çalıştırırken sürekli olarak Çağrı Yığını'nı günceller:

1. Kod çalışmaya başladığında, Global Yürütme Bağlamı oluşturulur ve Çağrı Yığını'na eklenir.
2. Bir fonksiyon çağrıldığında, o fonksiyon için yeni bir Fonksiyon Yürütme Bağlamı oluşturulur ve Çağrı Yığını'nın en üstüne eklenir. Bu bağlam aktif hale gelir.
3. Aktif bağlamdaki fonksiyon başka bir fonksiyonu çağırırsa, yeni bir bağlam oluşturulur ve yine yığının en üstüne eklenir.
4. Bir fonksiyonun çalışması bittiğinde, ilgili yürütme bağlamı yığından çıkarılır. Yığının bir altındaki bağlam tekrar aktif hale gelir.
5. Global Yürütme Bağlamı da dahil olmak üzere tüm bağlamlar yığından çıkarıldığında, programın yürütülmesi tamamlanır.

Örnek Senaryo: Fonksiyon Zinciri

Aşağıdaki basit fonksiyon zincirini ve Çağrı Yığını'nın nasıl değiştiğini inceleyelim:

function birinci() {
  console.log("Birinci fonksiyon başladı.");
  ikinci();
  console.log("Birinci fonksiyon bitti.");
}

function ikinci() {
  console.log("İkinci fonksiyon başladı.");
  ucuncu();
  console.log("İkinci fonksiyon bitti.");
}

function ucuncu() {
  console.log("Üçüncü fonksiyon başladı.");
  console.log("Üçüncü fonksiyon bitti.");
}

birinci();

Bu kodu çalıştırdığımızda Çağrı Yığını'nın durumu adım adım şöyle değişir:

1. Başlangıç: Çağrı Yığını boş.
2. birinci() çağrılır:
* [Global Yürütme Bağlamı]
* [Birinci Fonksiyon Yürütme Bağlamı] (yığına eklenir)
3. ikinci() birinci() içinden çağrılır:
* [Global Yürütme Bağlamı]
* [Birinci Fonksiyon Yürütme Bağlamı]
* [İkinci Fonksiyon Yürütme Bağlamı] (yığına eklenir)
4. ucuncu() ikinci() içinden çağrılır:
* [Global Yürütme Bağlamı]
* [Birinci Fonksiyon Yürütme Bağlamı]
* [İkinci Fonksiyon Yürütme Bağlamı]
* [Üçüncü Fonksiyon Yürütme Bağlamı] (yığına eklenir)
5. ucuncu() biter:
* [Global Yürütme Bağlamı]
* [Birinci Fonksiyon Yürütme Bağlamı]
* [İkinci Fonksiyon Yürütme Bağlamı] (yığından çıkarılır)
6. ikinci() biter:
* [Global Yürütme Bağlamı]
* [Birinci Fonksiyon Yürütme Bağlamı] (yığından çıkarılır)
7. birinci() biter:
* [Global Yürütme Bağlamı] (yığından çıkarılır)
8. Program biter: Çağrı Yığını boş.

Konsol çıktısı da bu sırayı takip eder:

Birinci fonksiyon başladı.
İkinci fonksiyon başladı.
Üçüncü fonksiyon başladı.
Üçüncü fonksiyon bitti.
İkinci fonksiyon bitti.
Birinci fonksiyon bitti.

Yürütme Bağlamı ve Çağrı Yığını Arasındaki İlişki

Yürütme bağlamı ve çağrı yığını, JavaScript'in nasıl çalıştığını anlamak için birbirini tamamlayan iki anahtar kavramdır. Biri "ne" çalıştığını (bağlam), diğeri ise "hangi sırada" çalıştığını (yığın) açıklar.

Akış Kontrolü

Çağrı Yığını, JavaScript motorunun programın akışını nasıl kontrol ettiğini gösterir. Her fonksiyon çağrısı bir yürütme bağlamı oluşturur ve bu bağlam yığına eklenir. Yığının en üstündeki bağlam her zaman aktif olan ve yürütülen bağlamdır. Bir bağlam tamamlandığında, yığından çıkarılır ve kontrol bir altındaki bağlama geçer. Bu, JavaScript'in tek iş parçacıklı doğasında, kodun deterministik bir sırayla çalışmasını sağlar.

Hata Yönetimi: Stack Overflow

Çağrı Yığını'nın boyutunun bir sınırı vardır. Eğer bir fonksiyon kendini çok fazla kez çağırırsa (rekürsif fonksiyonlarda yanlış bir temel durum veya sonsuz döngü), yığın kapasitesini aşabilir. Bu duruma "Stack Overflow" (Yığın Taşması) hatası denir.

function sonsuzDongu() {
  sonsuzDongu(); // Kendini tekrar tekrar çağırıyor
}
sonsuzDongu(); // Bu bir Stack Overflow hatasına yol açacaktır

Bu hata, JavaScript motorunun daha fazla yürütme bağlamını yığına ekleyemediğini ve programın durdurulduğunu gösterir. Hata mesajında genellikle hangi fonksiyonların yığında olduğu da listelenir, bu da hata ayıklama için faydalıdır.

Asenkron JavaScript ve Olay Döngüsü (Event Loop) ile İlişkisi (Kısaca)

JavaScript tek iş parçacıklı olmasına rağmen, asenkron işlemleri (API çağrıları, zamanlayıcılar vb.) Event Loop (Olay Döngüsü) ve Callback Kuyruğu (Callback Queue) yardımıyla yönetir.

* Asenkron bir işlem başlatıldığında, fonksiyon çağrısı Çağrı Yığını'na eklenir ve hemen çıkarılır (çünkü asenkron işlem arka planda devam eder).
* Asenkron işlem tamamlandığında, ilişkili callback fonksiyonu Callback Kuyruğu'na eklenir.
* Event Loop sürekli olarak Çağrı Yığını'nın boş olup olmadığını kontrol eder. Eğer yığın boşsa, Callback Kuyruğu'ndaki ilk callback fonksiyonunu alıp Çağrı Yığını'na ekler, böylece yürütülmesini sağlar.

Bu mekanizma, uzun süren işlemlerin ana iş parçacığını bloke etmesini önler ve JavaScript'in duyarlı kalmasını sağlar. Yürütme bağlamları ve çağrı yığını, senkron kodun nasıl çalıştığını açıklarken, Event Loop asenkron kodun bu senkron yapıya nasıl entegre olduğunu gösterir.

Pratik Uygulamalar ve Sıkça Yapılan Hatalar

Yürütme bağlamı ve çağrı yığını kavramlarını anlamak, günlük JavaScript geliştirme pratiklerinizde size önemli avantajlar sağlar. Bu bilgi, kodunuzu daha öngörülebilir hale getirir ve yaygın hataları önlemenize yardımcı olur.

Kapsam (Scope) Anlayışının Önemi

* var vs. let/const: var fonksiyon kapsamlıdır ve hoisting davranışı nedeniyle beklenmedik sonuçlara yol açabilir. let ve const ise blok kapsamlıdır ve Temporal Dead Zone (TDZ) ile daha öngörülebilir bir davranış sergiler. Bu farkı bilmek, değişken bildirimlerinde doğru anahtar kelimeyi seçmenizi sağlar ve kapsam hatalarını azaltır.
* Closure'lar: Bir iç fonksiyonun, tanımlandığı dış fonksiyonun kapsamındaki değişkenlere erişebilmesi durumuna closure denir. Bu, Lexical Ortam ve kapsam zinciri sayesinde mümkün olur. Closure'ları anlamak, ileri düzey JavaScript desenleri ve modül oluşturma için temeldir.

for (var i = 0; i < 3; i++) {
  setTimeout(function() {
    console.log(i); // Her zaman 3 yazdırır, çünkü i globalde değişir
  }, 100);
}

for (let j = 0; j < 3; j++) {
  setTimeout(function() {
    console.log(j); // 0, 1, 2 yazdırır, çünkü j her döngüde yeni bir blok kapsamına sahiptir
  }, 100);
}

this Bağlamı Yanılgıları

this anahtar kelimesinin dinamik doğası, özellikle fonksiyonları farklı bağlamlarda çağırırken veya callback'ler kullanırken sıkça hatalara yol açar.

* Metotları Ayırmak: Bir nesnenin metodunu ayrı bir değişkene atayıp çağırdığınızda, this genellikle window (veya undefined sıkı modda) olur, çünkü metot artık bir nesnenin bağlamında çağrılmamaktadır.
* Callback Fonksiyonları: Event handler'lar veya zamanlayıcılar gibi callback fonksiyonlarında this genellikle çağrı mekanizmasına göre değişir. Bu tür durumlarda bind(), call(), apply() kullanmak veya arrow fonksiyonları tercih etmek, this'i istediğiniz bağlama sabitlemek için yaygın çözümlerdir.

const kullanici = {
  ad: "Ayşe",
  selamla: function() {
    console.log("Merhaba, " + this.ad);
  }
};

kullanici.selamla(); // Merhaba, Ayşe

const selamlaFonksiyonu = kullanici.selamla;
selamlaFonksiyonu(); // Merhaba, undefined (this artık window'u gösteriyor)

// Çözüm: bind() ile bağlamı sabitleme
const bagliSelamla = kullanici.selamla.bind(kullanici);
bagliSelamla(); // Merhaba, Ayşe

Rekürsif Fonksiyonlar ve Yığın Taşması Riski

Rekürsif fonksiyonlar (kendini çağıran fonksiyonlar) güçlü araçlar olsa da, doğru bir temel durum (base case) olmadan kullanıldığında Stack Overflow hatasına neden olabilirler. Her rekürsif çağrı yeni bir yürütme bağlamı oluşturur ve Çağrı Yığını'na eklenir. Eğer bu çağrılar durdurulmazsa, yığın dolar ve program çöker. Rekürsif fonksiyon yazarken her zaman bir çıkış koşulu belirlediğinizden emin olun.

function faktoriyel(n) {
  if (n === 0) { // Temel durum
    return 1;
  }
  return n * faktoriyel(n - 1); // Rekürsif çağrı
}

console.log(faktoriyel(5)); // 120
// console.log(faktoriyel(10000)); // Bu, Stack Overflow hatasına yol açabilir!

Bu pratik bilgiler, JavaScript'in temel çalışma prensiplerini derinlemesine anlamanın, daha sağlam ve hatasız uygulamalar geliştirmenize nasıl yardımcı olduğunu göstermektedir.

Sonuç

Bu makalede, JavaScript'in temel çalışma mekanizmalarından ikisi olan Yürütme Bağlamı (Execution Context) ve Çağrı Yığını (Call Stack) kavramlarını detaylı bir şekilde inceledik. Yürütme bağlamının, kodun çalıştırıldığı soyut bir ortam olduğunu, Global, Fonksiyon ve Eval olmak üzere üç türü bulunduğunu ve Değişken Ortamı, Lexical Ortam ile this bağlamı gibi bileşenlerden oluştuğunu öğrendik. Çağrı Yığını'nın ise bu yürütme bağlamlarını LIFO prensibiyle yöneten bir veri yapısı olduğunu, fonksiyon çağrılarını nasıl takip ettiğini ve hata yönetiminde (Stack Overflow) oynadığı rolü gördük. Bu kavramları anlamak, JavaScript'in kapsam (scope), hoisting, this anahtar kelimesinin davranışı ve asenkron işlemler gibi karmaşık görünen yönlerini açıklığa kavuşturur. Artık kodunuzun sahne arkasında nasıl çalıştığına dair daha net bir resme sahipsiniz. Bu bilgi, daha bilinçli kod yazmanıza, hataları daha kolay ayıklamanıza ve JavaScript geliştirme becerilerinizi bir üst seviyeye taşımanıza yardımcı olacaktır.

Sıkça Sorulan Sorular (SSS)

Global Yürütme Bağlamı ne zaman oluşur?

Global Yürütme Bağlamı, JavaScript motoru bir script dosyasını ilk kez yüklediğinde veya bir tarayıcı sekmesi açıldığında, yani herhangi bir kod çalışmaya başlamadan hemen önce oluşturulur. Bir JavaScript uygulamasının ömrü boyunca yalnızca bir tane Global Yürütme Bağlamı bulunur.

Lexical Ortam ile Değişken Ortamı arasındaki temel fark nedir?

Değişken Ortamı (var değişkenleri ve fonksiyon bildirimleri için) ve Lexical Ortam (let, const değişkenleri ve fonksiyon bildirimleri için) bir yürütme bağlamının bileşenleridir. Temel fark, var değişkenlerinin Değişken Ortamında undefined ile başlatılarak "hoisting"e uğramasıdır. let ve const değişkenleri ise Lexical Ortamda tutulur ve oluşturma aşamasında başlatılmazlar; bu da onları tanımlanmadan önce erişmeye çalışıldığında "Temporal Dead Zone" (TDZ) hatasına yol açar ve blok kapsamı sağlarlar.

this anahtar kelimesi neden bazen kafa karıştırıcı olabilir?

this anahtar kelimesinin değeri, fonksiyonun nasıl çağrıldığına bağlı olarak dinamik olarak değiştiği için kafa karıştırıcı olabilir. Global bağlamda window'a (tarayıcıda) veya global'a (Node.js'te) işaret ederken, bir nesnenin metodu olarak çağrıldığında o nesneye işaret eder. Arrow fonksiyonları ise kendi this bağlamlarına sahip değildir ve çevreleyen Lexical Ortamdan this değerini miras alırlar. Bu farklı davranışlar, this'in değerini tahmin etmeyi zorlaştırabilir.

JavaScript tek iş parçacıklı (single-threaded) ise asenkron işlemleri nasıl yönetir?

JavaScript, tek iş parçacıklı olmasına rağmen, asenkron işlemleri (örneğin, ağ istekleri, zamanlayıcılar) Event Loop (Olay Döngüsü) ve Callback Kuyruğu (Callback Queue) adı verilen mekanizmalar aracılığıyla yönetir. Asenk

Yorumlar
İçeriği beğendiniz mi? Bir tartışma başlatın veya görüşlerinizi paylaşın.
Yorum Yaz

Bir yanıt yazın

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir

E-posta Bülteni
Yazılım Topluluğuna Katılın
En son güncellemeleri, yaratıcı ipuçlarını ve özel kaynakları doğrudan e-posta kutunuza alın. Tasarım ve inovasyonun geleceğini birlikte keşfedelim.