JavaScript’te Değişken, Scope ve Fonksiyon Kavramlarını Anlamak
Bu yazıda, JavaScript’te ki değişken (variable), bağlam (scope) ve fonksiyon (function) kavramlarını inceleyeceğiz.
--
JavaScript programlama dili web uygulamaları geliştirmek, HTML ve CSS’in yanı sıra web sayfalarına ek özellikler ekleyerek işlev kazandırmamızı sağlayan bir programlama dilidir. Eğer HTML, CSS ve JavaScript hakkında daha fazla bilgi edinmek isterseniz, buradaki yazımı okumanızı öneririm.
Değişkenler (Variables)
Değişkenler, hangi programlama dilinde olursa olsun öğrenilmesi gereken en temel konular arasındadır. Değişkenleri bir defa öğrendikten sonra farklı programlama dillerinde ki kullanımlarına alışmak çok kolay olur.
Peki, bu değişkenler ne işe yarar?
Değişken tanımlamak temel olarak verilerinizi bilgisayarın belleğinde (RAM’de) saklamanızı sağlar. Siz yeni bir değişken oluşturduğunuz zaman RAM’de yeni değişkeninizin boyutu kadar bir yer ayrılır ve veriniz o yere kaydedilir. Fakat unutulmaması gereken nokta ise bilgisayarınızı kapatıp açtığınızda RAM’deki veriniz silinir. Bu yüzden değişkenler bilgisayar belleğinde geçici olarak dururlar. C gibi makine diline yakın programlama dillerinde değişkenleri saklayacağımız yerlere — belleğe doğrudan müdahale edebilirken daha gelişmiş programlama dillerinde (JavaScript, Python gibi) buna gerek kalmamıştır. Bu durumun getirdiği güzelliklerden bir tanesi ise bellekte yaşayabileceğiniz bug’ların önüne geçilmesini sağlamış olmasıdır. Dilerseniz değişkenleri birde JavaScript’in içerisinde inceleyelim;
JavaScript’in en son sürümüyle birlikte (bu yazı yazıldığında en son sürüm ES6) toplam 3 farklı değişken tanımlama yöntemimiz oldu. Bunlar; var, let ve const.
Yukarıda bu üç farklı değişken tanımlama yöntemini görüyorsunuz. deger1, deger2, deger3'ler ise değişkenlerimizin isimleri. Yanlarındaki sayılar ise değişkenlerimizin değerleri. JavaScript üzerinde console.log(deger1 + deger2) yazdığınız zaman ekrana 24 sayısını yazdıracaktır. Burada console.log( ) ekrana çıktı yazdıran bir fonksiyondur fakat şimdi bunu kafanıza takmayın, ileride fonksiyonları da açıklayacağım. Şimdi ise gelelim var, let ve const’un kelime anlamlarına. Unutmayın, bazen bir şeyi ezberlemek yerine onun nedenini bilmek büyük bir sorunun çözümüne yardımcı olabilir ve aynı zamanda akılda daha kalıcı olur.
- var: “Variable (Değişken)” kelimesinin kısaltılmış halidir.
- let: let belirteci, günümüz İngilizce’sinden gelmektedir. Örneğin; “Let deger2 is equal to 12” yani, “deger2 12'ye eşit olsun.”
- const: const ise İngilizce’de “constant” yani sabit kelimesinden kısaltılmış halidir.
Bir değişkeni const ile tanımladığımız zaman o değişkenin değerini daha sonra değiştiremiyoruz. Örneğin pi sayısı bir sabittir dolayısıyla yazdığınız programın ilerleyen bölümlerinde değiştirmeye gerek duymayacağımızdan dolayı değişkenimizi, “const pi = 3.14” olarak tanımlarsak doğru yapmış oluruz. Eğer pi değişkenine yeni bir değer atamaya kalkarsanız, değişkeni const ile tanımladığınızdan dolayı hata alırsınız. Değişken tanımlamalarını doğru kullanırsanız şayet, bilgisayar belleğinizi de doğru kullanmış olursunuz.
Geri kalan diğer değişken tanımlama yöntemlerini Scope bölümü içerisinde anlatacağım. Çünkü temel olarak let ve var’ın farkını anlatabilmek için Scope kavramını anlamak gerekiyor.
Bağlam (Scope)
Scope kavramını anlamak ve anlatmak bazen güç olabiliyor. Eğer program içerisinde scope ile ilgili problemleriniz varsa, büyük problemleriniz var demektir 😖 Bu yazıda scope’un derinlerine inmeyeceğiz bunun sebebi scope kavramının sandığınızdan daha derin bir konu olması. Ben size buz dağının biraz daha görünen kısımlarını anlatacağım.
Scope, değişkenlerinize nereden erişebileceğinizi belirleyen kurallar bütünüdür. Şimdi bunu size let ve var’ın farklılıklarını kullanarak açıklıyayım.
- let, block-scope bir değişken tanımlama yöntemidir. block dediğimiz yapılar ise küme parantezlerinin arasında kalan yerdir. let ile tanımlanan değişkenlerin değeri daha sonra değiştirilebilir fakat aynı değişkeni tekrar tanımlayamazsınız.
- var ise globally-scope bir değişken tanımlama yöntemidir. Değerini daha sonra değiştirebilir ve tekrar aynı değişkeni tanımlayabilirsiniz.
Şimdi basit bir JavaScript programı yazarak block-scope ve globally-scope kavramlarını daha iyi anlayalım;
Yukarı da let’in tekrardan tanımlanamayacağını söylemiştik fakat yukarıda ki koda bakarsanız hem fonksiyonun dışarısında hem de fonksiyonun içerisinde aynı değişkeni tekrar tanımlamışız buna rağmen herhangi bir hata almadan kodumuz çalışmış. Peki buna ne sebep oldu? Tabi ki Scope!
let ile tanımlanan değişkenleri tekrar tanımlanamayacağını söyledik fakat aynı zaman da let’in block-scope özellikte olduğunu da söyledik. Kodu dikkatli incelerseniz fonksiyonda küme parantezleri ({}) var. Dolayısıyla burada bir block yapısı vardır. Fonksiyon içerisinde let ile tanımladığınız değişkenin özelliğinin block-scope olması demek, değişkenin bağlamının aslında bulunduğu block’un içi olması demektir. Mevcut örneğimizi biraz daha geliştirelim;
Yukarıdaki kodu çalıştırdığımız zaman bize “SyntaxError: Identifier ‘hayvan’ has already been declared” hatasını verir. Bu hata bize hayvan adlı değişkenin daha önceden tanımlandığını bildirir. Bu hatanın nedeni ise aynı block içerisinde iki kere “let hayvan” diyerek tanımlama yapmamızdan dolayıdır. Eğer aynı block içerisinde let’i kullanmadan hayvan= “fil” yazsaydık kodumuz düzgün çalışırdı çünkü değer tanımlaması değil değer ataması yapmış olurduk.
Şimdi gelin yukarıda ki örneği biraz değiştirerek birde var’ın ne olduğuna bakalım;
Hatırlıyorsak eğer var ile hem değişken tanımlamasını tekrar yapabiliyorduk hem de değer ataması yapabiliyorduk. Yukarıdaki kodda gördüğünüz üzere aynı fonksiyonun içerisinde iki kere var’ı kullanarak değişken tanımlaması yaptık ve hiçbir hata almadan kodumuz düzgün bir şekilde çalıştı.
let ile var değişken belirteçlerinin temel farkları böyleydi, şimdi ise Scope’ta değişkenlere erişim kurallarını inceleyelim;
Scope’ta Değişkenlere Erişim
let veya const ile tanımlanan değişkenler, block-scope olduğu için içeride ki block’ta tanımlanmış bir değişkene dışarıdan erişemiyoruz. Örneğin;
Yukarıdaki kodu çalıştırdığımızda “ReferenceError: sehir is not defined” yani sehir isimli değişken tanımlanmadığı hatasını bildirir. Fakat dışarıda tanımladığımız bir değişkene içeriden erişmeye çalıştığımız zaman bunu başarıyla yapabiliriz;
Yukarıda ki kod başarıyla çalışır. let için durum böyleyken yazının başında da belirttiğimiz üzere var globally-scope’tur yani, var ile tanımlanmış bir değişken block yapısının içerisindeyse bile ona dışarıdan erişebilirsiniz.
Yukarıdaki kod düzgün bir şekilde çalışır. Fakat burada önemli bir not düşmek gerekir. var her ne kadar globally-scope olsa dahi fonksiyonların içerisindeki var ile tanımlama yapılmış değişkenlere, fonksiyonun dışarısından erişemeyiz;
Yukarıda ki kodu çalıştırdığımızda “ReferenceError: sehir is not defined” hatasını verir. Fonksiyon içerisinde var ile tanımlaması yapılmış değişkenlere dışarıdan erişemediğimiz için bazı kaynaklarda var için function-scope’ta denilmektedir.
Bu yazıyı okuduğunuza göre JavaScript veya programlamada yeni olduğunuzu varsayarak scope’u giriş seviyesinde yeterince anlattığımı düşünüyorum. Hız kesmeden son olarak fonksiyonlardan bahsedelim.
Fonksiyonlar (Functions)
Fonksiyonların temel mantığı tekrar tekrar aynı kodu yazmak yerine o kodu bir yapının içerisine bir seferde yazıp yapıyı gereken yerde çağırmaktan geçiyor. Bu sayede yazılımcılıkta en tehlikeli şeylerden birisi olan kod tekrarından kurtulmuş oluyorsunuz. Ayrıca yazdığınız kod daha anlaşılır ve daha kısa oluyor.
Fonksiyonların lisede öğrendiğimiz fonksiyonlardan aslında hiçbir farkı yok. Hatırlarsanız lisede aldığımız temel matematik eğitiminde fonksiyonları f(x) olarak tanımlıyorduk ve x yerine bir değer verip bir çıktı elde ediyorduk. JavaScript’te de aslında aynı mantık çalışıyor. Hemen bir örnek verelim;
JavaScript’te fonksiyon tanımlamak için function ön ekini yazmak gerekir. Böylelikle JavaScript bizim bir fonksiyon yazdığımızı anlar. Daha sonra fonksiyon ismini yazarız ve parantezler içerisini parametre isimlerini yazarız. Yukarıda ki örnekte parametre isimleri sayi1 ve sayi2'dir. Parametre isimleri demem sizi yanıltmasın aslında parametreler de birer değişkendir.
Bir fonksiyon sadece 2 parametre değil 2'den daha fazla parametre alabilir. Parametre sayısı size bağlıdır, isterseniz hiç parametre vermeyebilirsiniz. Bu durumda “function fonksiyonIsmi()” yazmanız yeterli olacaktır.
Yukarıda ki örnekte açıkça gördüğünüz üzere fonksiyonumuz aslında bir toplama işlemi yapıyor ve toplam’ı çağrıldığı yere götürüyor. toplam değişkenini çağrıldığı yere götürmesini sağlayan yapımız return’dür. Return kelimesinin İngilizce’deki karşılığı geri dön demektir. Şimdi buna bir örnek verelim;
En başta fonksiyonumuzu tanıttık, daha sonra topla isimli fonksiyonumuzu dışarıdaki bir değişkene parametre değerleri 12 ve 23 olacak şekilde atadık. Bu ne yaptı? Fonksiyon ilk olarak 12 ve 23 değerlerini kendi içinde topladı ve bunu fonksiyon içindeki toplam değişkenine atadı. Daha sonra da toplam değişkenini return yardımıyla döndürdü yani toplam’ı çağrıldığı yere geri götürdü. Bu sayede let sonuc = 35 oldu. Bunu yazdırdığımızda bize 35 çıktısını verdi. Return’ü anlamak yeni başlayan insanlar için oldukça kafa kurcalayıcı olabilir. Bu yüzden endişelenmeyin ve kendinize biraz zaman tanıyıp bol bol alıştırma yapın. Eğer return’ün mantığını biraz daha iyi anlamak isterseniz buradaki yazımı okuyabilirsiniz.
Son olarak bahsetmek istediğim şey ise return’ün kullanılmadığı senaryolar;
Yukarıda return’ü kullanmadık fakat dikkat ettiyseniz topla fonksiyonunu da herhangi bir değişkene atamadık. Eğer atasaydık hata alacaktık çünkü topla fonksiyonu herhangi bir değer döndürmüyor. Yani çağrılacağı yere herhangi bir değer götürmüyor olacaktı.
Yazımı noktalamadan önce bu yazıyı buraya kadar sıkılmadan okuduysanız size çok teşekkür ederim. Umarım bu yazı size değişkenler, scope ve fonksiyonlar hakkında edinmek istediğiniz bilgiyi vermiştir. 😃