Variable ve Lexical Environment Nedir? Scope Chain Bu İşin Neresinde?

Java Script’in Temel Kavramları

Emre SERBEST
4 min readApr 25, 2021
JavaScript

Bir önceki yazımda Execution Stack ve Execution Context kavramlarına değinmiştim. Bu yazıyı okumadan önce aşağıdaki blog yazıma göz atmanızı tavsiye ederim.

Eğer ben zaten okumuştum diyorsanız o halde kaldığımız yerden devam etme vaktimiz geldi.

Her fonksiyon çağırıldığında ona ait Execution Context’in, stack içine eklendiğini söylemiştim. Fakat bu Execution Context nasıl yaratılıyor kısmına değinmemiştim. Execution Context içinde this anahtar kelimesinin atama bilgisi, Variable Environment ve Lexical Environment içerik bilgilerinden oluşur.

Creation Stage (Yaratılma Aşaması)

  • this anahtar kelimesinin atama işlemi bu aşamada gerçekleşir.
  • Variable Environment (Değişken Ortamı) bu aşamada tanımlanır ve var ile tanımlanan değişken bilgileri undefined olarak tanımlanır.
  • Lexical Environment (Anlamsal Ortam) bu aşamada Variable Environment’in kopyasıdır.

Execution Stage (Çalışma Aşaması)

  • Tanımlanan değişkenlerin değer atamaları yapılır.
  • Lexical Environment diğer fonksiyon bağlamının diğer fonksiyon bağlamlarıyla ilişkilendirmesini yapar

Bu kod parçası çalışırken neler oluyor, ekrana ne, neden yazdırılıyor kısmını görsel üzerinden anlatmaya çalışacağım.

Execution Stack ve Context
Resim 1: Execution Stack ve Context

Öncelikle kodumuzun global context, greet ve welcome fonksiyonlarının contextleri olmak üzere 3 ana parçadan oluştuğunu söyleyebiliriz. welcome() ve greet() fonksiyonlarının aynı seviyede -global context’e bağlı olarak- tanımlanmıştır. Örnek kod parçasının 10. satırında greet() fonksiyonu çağırıldığında Execution Stack’in durumunu resimdeki gibi düşünebiliriz. greet() fonksiyonun içinde(satır 4) konsol ekranına ‘Hello ’ ve name değişkenin tanımlı olduğu değeri yazdırmak için bir kod parçası olduğunu görüyoruz. Fakat bir sorun var gibi çünkü greet() fonksiyonunun contextinde name değişkeni tanımlanmamış. Bu durumda bir JavaScript kodu nasıl çalışır? Fonksiyonun içinde kullanılan değişkenler öncelikle fonksiyonun kendi contexti içerisinde aranır. greet() fonksiyonunun Execution Context’inde name değişkeni bulunamadığından dolayı greet() fonksiyonun bağlı olduğu bir üst context olan Global Context’te olup olmadığı kontrol edilir. Bu örnekte greet() fonksiyonunun welcome() fonksiyonun içinden çağırıldığı için eğer ekrana ‘Unknown Guest’ yazdırılacağını düşündüyseniz maalesef yanıldınız.

Gelin şimdi benzer fakat biraz daha karışık bir kod örneğinde ekrana ne yazılacağını adım adım inceleyelim.

Aşağıda bulunan Resim 2 de contextlerin birbiriyle ilişkisini göstermeye çalıştım. Örneğin drive() fonksiyonunun diğer contextlerle ilişkisine baktığımızda drive() içinde kullanılan değişkenler ve fonksiyonlar önce drive() fonksiyonunun kendi contextinde aranır. Bulunamayan sonuçlar için parent context olan buyVehicle()’ın contextine erişilir. Çünkü drive fonksiyonu buyVehicle() fonksiyonun contextinde tanımlanmıştır. Burda da bulamayan değişkenler için global context’e erişilir.

Variable Environment & Lexical Environment
Resim: 2 Execution Contextler Arası İlişki

Satır 26: ekrana yazdırılmak istenen car değişkeni içinde bulunulan Global Context içinde tanımlı olduğu için ekrana ilk olarak I have an Audi yazdırılır.

Satır 28: walk() fonksiyonu çağırılır ve (satır 23) ekrana yazdırılmak istenen place değişkeni walk() contextinde olmadığı için parent context olan Global Context içinden okunur ve ekrana I’m going to London yazdırılır.

Satır 29: buyVehicle() fonksiyonu çağırılır. İki farklı car ve motorCycle değişkenleri bu context içinde tanımlanır ve ekrana bu context içinde daha önce tanımlı bir car değişkeni olduğu için I bought a Mercedes yazdırılır.

Satır 17: drive() fonksiyonu çağılır. Burada da car adında bir değişken farklı bir değerle tanımlandıktan (satır 11) sonra ekrana I am driving a BMW yazdırılır. motorCycle değişkeni tanımlı olmadığından dolayı parent context olan buyVehicle() contextinden okunur ve ekrana (satır 12) I have a Yamaha yazdırılır.

Satır 13: ekrana yacht değişkeni kullanılarak I have a ... yazdırılmak istenir fakat bu context içinde yacht değişkeni tanımlı olmadığından dolayı parent context olan buyVehicle() contextine erişilir. yacht değişkeni burada da tanımlı olmadığından Global Context’e erişilip bu değişken aranır. Fakat burada da yacht ismiyle bir değişken tanımlanmadığı için ReferenceError: yacht is not defined hatası fırlatılır.

Not: walk() contexti içinde tanımlı bir yacht değişkeni vardır fakat bu contextler arasında bir bağlantı olmadığı için bu değişkene erişim sağlanamaz.

Özetlemek gerekirse Variable Environment her fonksiyonun kendi içinde tanımlanan fonksiyonların ve değişken değerlerinin saklandığı yer. Lexical Environment ise bir context içinde tanımı bulamayan bir değişkenin hangi contexte araması gerektiğinin adresinin tutulduğu yapı olarak düşünülebilir. Contextler arasındaki bu zincirli ilişki de Scope Chain olarak adlandırılır. Bir sonraki blog yazısında görüşmek üzere.

Kaynaklar:

--

--