JavaScript’te “scope” ve “closure” kavramları
JavaScript’te scope ve closure, kodunuzu doğru bir şekilde yazmanız için bilmeniz gereken önemli kavramlardır. Bu kavramlar kabaca değişkenlerin ve fonksiyonların nasıl kullanıldığına ve nerede tanımlandığına dair kuralları belirler diyebiliriz.
İlk önce sırayla bu kavramların kısaca bir tanımını yapıp örnek kodlar üzerinde ne işe yaradıklarını gösterelim.
Scope (kapsam), bir programda değişkenlerin ve fonksiyonların erişebilir olduğu alanları ifade eder.
JavaScript’te iki tür scope vardır: global scope (genel kapsam) ve local scope (yerel kapsam)
Global scope (genel kapsam), kodun herhangi bir yerinde tanımlanmış olan değişkenlerin ve fonksiyonların tüm kodda erişilebilir olması durumudur.
Local scop (yerel kapsam), bir fonksiyonun veya bloğun içinde tanımlanan değişkenlerin yalnızca o fonksiyon veya blok içinde erişilebilir olmasıdır.
⭐ JavaScript’te lobal scope kullanımı:
1 2 3 4 5 6 7 8 |
// Global scope var globalVariable = "Ben global bir değişkenim."; function sayHello() { console.log("Merhaba " + globalVariable); } sayHello(); // "Merhaba Ben global bir değişkenim." |
Yukarıdaki örnekte globalVariable
olarak adlandırılan değişkenimiz global bir değişken olarak tanımlanmıştır ve sayHello()
fonksiyonunda kullanılmıştır. sayHello()
fonksiyonu herhangi bir problem yaşamadan global scope’da tanımlandığı için globalVariable
değişkenine erişebilmiştir.
⭐ JavaScript’te her bir fonksiyon, kendi kapsamını oluşturur ve bu kapsam ile ilgili fonksiyonun içinde tanımlanan değişkenlere erişilebilirlik belirlenmiş olur.
Örneğin aşağıdaki kodu incelediğinizde, x
değişkeni myFunction
fonksiyonunun kapsamında tanımlanmıştır ve dolayısıyla sadece myFunction
fonksiyonu içinde erişilebilir olmaktadır.
1 2 3 4 5 6 7 |
// Local scope function myFunction() { var x = 10; console.log(x); // 10 } console.log(x); // ReferenceError: x is not defined |
❗ Çoğu programlama dili blok kapsamlıdır, yani her yeni küme parantezi { } ile yeni bir lexical environment (sözcük çerçevesi) oluşturulur. Ancak JavaScript fonksiyon kapsamlıdır, yani yalnızca global kapsamda fonksiyon anahtar kelimesini gördüğünde yeni bir yerel ortam oluşturur.
❗ Local scope (yerel kapsam), sadece fonksiyonlarla sınırlı değildir. İki durumda daha local scope oluşturulur:
➡️ if
, for
, while
gibi kontrol yapıları da kendi içlerinde local scope oluştururlar. Örneğin:
1 2 3 4 5 6 7 |
// if (true) { var message = "Merhaba Dünya!"; console.log(message); //"Merhaba Dünya!" } console.log(message); // "Merhaba Dünya!" |
Yukarıdaki örnekte if
bloğu içinde message
değişkeni tanımlandığı için local scope olmaktadır. if
bloğunun dışındaki console.log()
çağrısında da message
değişkenine erişilebilir.
➡️ ES6 ile birlikte kullanıma sunulan let ve const anahtar kelimeleri blok kapsam oluşturmaktadır. Örneğin:
1 2 3 4 5 6 7 |
// if (true) { let message = "Merhaba Dünya!"; console.log(message); //Merhaba Dünya! } console.log(message); // ReferenceError: message is not defined |
Yukarıdaki örnekte message
değişkeni let
anahtar kelimesi ile tanımlanmıştır ve bu nedenle sadece if bloğu kapsamında geçerlidir ve dışarıdan erişilemez. Bu nedenle ikinci console.log()
çağrısında ReferenceError
hatası alınır.
❗ Buna karşılık var anahtar kelimesi ile oluşturulan değişkenler bir blok içinde görünseler bile fonksiyon kapsamlıdırlar. Örneğin:
1 2 3 4 5 6 7 |
// var if (true) { var message = "Merhaba Dünya!"; console.log(message); //Merhaba Dünya! } console.log(message); //Merhaba Dünya! |
Var anahtar kelimesi ile tanımlanan message
değişkeni bir blok içinde dahi olsa fonksiyon kapsamlı olduğu için dışarıdan da erişilebilmiştir.
JavaScript’te closure (kapama), bir iç fonksiyonun, dış fonksiyonun kapsamındaki değişkenlere erişebilmesi durumudur.
⭐ Closure ile iç fonksiyon, dış fonksiyonun kapsamındaki değişkenleri, dış fonksiyon çalışmasını tamamladıktan sonra bile kullanabilir. Bu nedenle, closure, bir fonksiyonun değişkenleri hatırlamasına ve sonraki çağrılarda bu değişkenleri kullanabilmesine olanak tanıdığından oldukça önemli bir kavramdır.
1 2 3 4 5 6 7 8 9 |
//Closure function add(x) { return function(y) { return x + y; } } let add5 = add(5); console.log(add5(3)); // 8 |
Yukarıdaki örnekte add
isimli bir fonksiyon tanımlanmıştır ve x
parametresi almakta ve fonksiyonumuz içinde bir fonksiyon döndürmektedir. Döndürülen fonksiyon, add
fonksiyonunun bir değişkeni olan x
‘i hatırlayabilir (işte tam bu noktada closure özelliği devreye girmiştir).
Daha sonra add(5)
ile çağrıldığında, döndürülen fonksiyon, x
değerini 5 olarak hatırlayacak ve add5(3)
çağrısı yapıldığında 5 ve 3’ü toplayarak sonuç olarak 8 döndürecektir. Burada x
değişkeni, add
fonksiyonunun çağrıldığı sırada ortaya çıkan yerel bir değişken olmadığı halde içerideki fonksiyon tarafından kullanılabilmiştir. Böylece, add5
fonksiyonu add
fonksiyonundan çıktıktan sonra bile x
değişkenine erişebilmektedir.
Umarım JavaScript’teki scope ve closure kavramları net bir şekilde anlaşılmıştır. Eksik, hata veya sormak istediğiniz sorular için yorum bırakabilirsiniz.