- JavaScript Değişkenleri
- Değişken Tanımlama Kuralları ve İsimlendirme Prensipleri
- JavaScript Değişken Türleri: var, let ve const
- Var Anahtar Kelimesi: Tarihsel Kullanım ve Teknik Dezavantajlar
- Let Anahtar Kelimesi: Blok Kapsamlı ve Kontrollü Değişken Yönetimi
- Const Anahtar Kelimesi: Sabitlik ve Güvenli Referans Yönetimi
- Değişken Bildirme, Başlatma ve Yeniden Atama
- JavaScript Kapsam Kavramı (Scope)
- Programlamanın Temel Taşı
- Programlamada Değişkenin Evrimi ve Felsefesi
Değişkenler ( Ana Konu Giriş )
Verilerin bellekte nasıl işlendiğini, let, const ve var arasındaki
farkları tüm
detaylarıyla derinlemesine inceleyin.
Modern JavaScript dünyasında değişken yönetiminin altın kurallarını
ve gerçek
hayat senaryolarındaki karşılıklarını bu bölümde kazanacaksınız.
JavaScript Değişkenleri Detaylı Açıklama ve Kullanım Prensipleri
JavaScript'te değişkenler, verileri geçici olarak depolamak ve yönetmek için kullanılan adlandırılmış soyutlama alanlarıdır.
Etiketli Kutu Analojisi: Basitçe ifade etmek gerekirse, bir değişken tanımladığınızda, bilgisayarın belleğinde ( RAM ) o değere erişmek için kullandığınız etiketli bir kutu oluşturmuş olursunuz.
Geliştirici, bu ismi ( etiketi ) kullanarak kutunun içinde depolanan değere ulaşabilir, onu okuyabilir veya içeriğini değiştirebilir.
Değişkenler, sakladıkları verinin türüne bakılmaksızın ( sayılar, metinler, karmaşık nesneler vb. ) bu adlandırılmış bellek konumlarını temsil ederler.
Modern Tanımlama YöntemleriDilin evrimi boyunca değişken tanımlama yöntemleri büyük ölçüde değişmiştir:
- ES6 Öncesi: Yaygın olarak sadece var anahtar kelimesi kullanılırdı.
- Modern JavaScript (ES6+): Daha güvenli kod yazımı için let ve const anahtar kelimeleri kullanıma sunulmuştur.
Bu üç anahtar kelime ( var, let, const), iki temel davranış açısından kritik farklılıklar gösterir:
- Kapsam ( Scope ): Değişkenin kodun neresinden erişilebilir olduğu.
- Yeniden Atanabilirlik ( Reassignment ): Değişkenin değerinin sonradan değiştirilip değiştirilemeyeceği.
Bu farkları anlamak ve doğru anahtar kelimeyi seçmek, sadece kodu çalıştırmak için değil, aynı zamanda daha güvenilir, temiz ve hatasız programlar yazmak için temel bir gerekliliktir.
JavaScript değişkenlerinin bu esnek yapısı, dilin dinamik doğasını yansıtır ve programcıya verileri tiplerden bağımsız olarak hızlıca manipüle etme gücü verir.
const isim = "Ali";
console.log(isim);
// isim adlı bir değişkende "Ali" bilgisini sakladık ve ekrana yazdırdık.
const anahtar kelimesi, JavaScript'te değiştirilemez bir değişken tanımlamak için kullanılır. Bu örnekte isim adında bir değişken oluşturulmuş ve "Ali" değeri atanmıştır. const ile tanımlanan değişkenler, bir kez değer atandıktan sonra yeniden atama yapılamaz. Bu, programın daha güvenli ve öngörülebilir olmasını sağlar.
Değişken adı olarak isim kullanılmış, bu da değişkenin ne tür bir veri sakladığını açıkça belirtir. Bu tür basit örnekler, programlamaya yeni başlayanlar için değişken kavramını anlamak ve JavaScript'in temel sözdizimini öğrenmek için idealdir. Değişkenler, programlama dillerinde veri saklamak ve bu verileri daha sonra kullanmak için kullanılan temel yapılardır.
console.log() metodu, JavaScript'te değişkenlerin veya değerlerin tarayıcı konsoluna yazdırılmasını sağlar. Bu örnekte isim değişkeninin değeri konsola yazdırılmaktadır. Bu metod, kodun çalışıp çalışmadığını kontrol etmek, değişkenlerin değerlerini görmek ve hata ayıklama yapmak için kullanılır.
Kodun ilk satırında const belirleyicisi kullanılarak bellekte değiştirilemez bir alan oluşturulur. isim etiketi bu alana referans verirken, "Ali" metinsel verisi bu adrese kalıcı olarak hapsedilir.
Giriş/Çıkış İşlemi:İkinci satırda console.log() fonksiyonu tetiklenir. JavaScript motoru parantez içindeki isim değişkenini gördüğünde, bellekte bu isme karşılık gelen değeri ( ""Ali"" ) bulur ve tarayıcı konsoluna veri akışını sağlar.
İşlem Akışı:Program yukarıdan aşağıya doğru ilerler; önce veri depolanır, ardından depolanan bu veri çağırma metoduyla kullanıcıya sunulur. const kullanımı sayesinde bu akış boyunca verinin bütünlüğü garanti altına alınmış olur.
Eğer const ile tanımlanmış bir değişkene yeniden değer atamaya çalışırsanız, tarayıcı konsolunda şu hatayı görürsünüz:
TypeError: Assignment to constant variable.
Bu hata, const ile tanımlanan değişkenlerin salt okunur (read-only) olduğunu ve yeniden atama yapılamayacağını gösterir. Bu durumda, değişkenin değerini değiştirmek istiyorsanız, let veya var kullanmanız gerekir.
Değişken isimleri anlamlı ve açıklayıcı olmalıdır. isim gibi basit ve anlaşılır isimler kullanın.
const Kullanımı:Değeri değişmeyecek değişkenler için her zaman const kullanın. Bu, kodunuzun daha güvenli ve bakımı kolay olmasını sağlar.
Konsol Kullanımı:console.log() metodunu hata ayıklama ve değişken değerlerini kontrol etmek için kullanın, ancak production kodunda gereksiz console.log() çağrılarını kaldırın.
let fiyat = 100;
console.log(fiyat);
fiyat = 120; // fiyat güncellendi
console.log(fiyat);
// Aynı değeri tekrar tekrar yazmak yerine fiyat değişkenini kullanıldı.
let anahtar kelimesi, JavaScript'te değeri daha sonra değiştirilebilen bir veri tanımlamak için kullanılır. Bu örnekte fiyat adında bir değişken oluşturulmuş ve başlangıç değeri 100 olarak atanmıştır.
Değişkenin en büyük avantajı, değerin kodun ilerleyen aşamalarında güncellenebilmesidir. Örnekteki fiyat = 120; satırı, bellekteki eski değeri yeni değerle değiştirir. Bu sayede aynı veriyi tekrar tekrar yazmak yerine tek bir merkezi değişkeni yönetmiş olursunuz.
console.log() metodunu incelediğimizde; güncelleme öncesi yapılan ilk çağrı konsola 100 yazdırırken, güncelleme sonrası yapılan ikinci çağrı güncel değer olan 120 sonucunu verir.
İlk satırda let anahtar kelimesi kullanılarak fiyat isimli bir bellek alanı ayrılır ve bu alana başlangıç değeri olarak 100 tam sayısı atanır.
Değer Güncelleme (Mutation):Kodun orta kısmında fiyat = 120; ifadesi ile bellekteki mevcut veri adresine gidilir. Eski 100 değeri silinerek yerine yeni 120 verisi yazılır; bu işlem let yapısının dinamik doğasını temsil eder.
Çıktı Karşılaştırması:Program akışı sırasında yapılan iki ayrı console.log() çağrısı, aynı değişken isminin farklı zaman dilimlerinde farklı değerleri temsil edebileceğini kanıtlar. Bu, programın durum (state) yönetiminin temel mekanizmasıdır.
let ile tanımlanan bir değişkeni aynı kapsamda tekrar tanımlamaya çalışmak hataya yol açar:
SyntaxError: Identifier 'fiyat' has already been declared
Bir diğer yaygın hata, değişkeni tanımlamadan ona erişmeye çalışmaktır. Bu durumda JavaScript motoru değişkeni "Temporal Dead Zone" içinde bulur ve erişim hatası verir.
Eğer bir değerin kod boyunca hiç değişmeyeceğinden eminseniz const, değişme ihtimali varsa let kullanın. var kullanımından kaçının.
Anlamlı İsimlendirme:Değişken isminiz içerdiği veriyi temsil etmelidir. f yerine fiyat veya urunUcreti gibi açıklayıcı isimler tercih edin.
Blok Kapsamı:let blok kapsamlıdır. Bu özelliği kullanarak değişkenlerin sadece ihtiyaç duyulan süslü parantez { } içerisinde yaşamasını sağlayarak bellek yönetimini optimize edebilirsiniz.
let puan = 0;
console.log(puan);
puan = puan + 10;
console.log(puan);
// puan değişkeni zamanla değişebildiği için let kullandık.
Bu örnekte puan adında bir değişken oluşturulmuş ve oyunlarda sıkça gördüğümüz bir başlangıç değeri atanmıştır. let kullanımı, bu değerin oyun akışına göre değişeceğini sisteme bildirir.
puan = puan + 10; satırı, programlamadaki en temel mantıklardan birini içerir. JavaScript önce sağ tarafı hesaplar (0 + 10), ardından bulduğu sonucu tekrar soldaki puan değişkeninin içine yazar. Böylece değişkenin değeri kümülatif olarak artar.
Değişkenin güncellenmesi, önceki değerin silinip yerine yeni sonucun yazılmasıdır. İlk console.log(puan); sıfır çıktısını verirken, matematiksel işlemden sonraki çağrı güncel skor olan 10 değerini görüntüler.
let puan = 0; satırı ile birlikte JavaScript motoru bellekte sayısal bir alan ayırır ve bu alanı 0 değeriyle ilklendirir.
Sağdan Sola Değerlendirme:Örneğimizin içerisinde ki puan = puan + 10; ifadesinde motor önce atama operatörünün sağ tarafını işler. Mevcut bellek değerini alır, 10 ile aritmetik toplama yapar ve geçici bir sonuç üretir.
Yeniden Yazma (Overwrite):Hesaplanan yeni değer, puan etiketinin işaret ettiği bellek adresine geri gönderilir. Bu işlem sonucunda eski veri kalıcı olarak silinir ve değişkenin güncel durumu (state) 10 olarak güncellenmiş olur.
Eğer değişkeni güncellemeye çalışırken değişken ismini yanlış yazarsanız, şu hatayı alırsınız:
ReferenceError: paun is not defined
Ayrıca, sayısal bir değişkene metin eklemeye çalışmak ( puan + "10" gibi ifadeler) hata vermez ancak sonucu "010" şeklinde bir metne dönüştürerek mantıksal hatalara yol açar.
Örnek içerisinde ki puan = puan + 10; ifadesi yerine profesyonel kodlarda genellikle daha kısa olan puan += 10; yazımı tercih edilir. Bu kullanım kodu daha temiz ve okunabilir kılar.
Tutarlı Başlatma:Sayısal işlemler yapacağınız değişkenlere mutlaka 0 veya başlangıç değerini atayın. Tanımlanmamış (undefined) bir değişkenle matematiksel işlem yapmak NaN (Not a Number) hatasına sebep olur.
Amaç Odaklılık:Değişken ismini sadece "sayi" veya "x" yerine "puan", "skor" veya "toplamTutar" gibi projedeki amacına uygun seçmek, kodun dökümantasyon kalitesini artırır.
var sehir = "Ankara";
console.log(sehir);
sehir = "İstanbul";
console.log(sehir);
// Çalışır ama modern JavaScript’te let ve const tercih edilir.
Bu örnekte var anahtar kelimesi kullanılarak sehir adında bir değişken tanımlanmıştır. var, JavaScript'in başlangıcından beri var olan geleneksel değişken tanımlama yöntemidir.
Değişken başlangıçta "Ankara" değerini almış, ardından sehir = "İstanbul"; satırı ile bu değer güncellenmiştir. var ile tanımlanan değişkenler, tıpkı let gibi sonradan yeni bir değer alabilirler.
Konsol çıktıları incelendiğinde, JavaScript motorunun satır satır ilerleyerek her iki aşamada da o anki güncel şehir bilgisini başarıyla ekrana yazdırdığı görülür.
var sehir = "Ankara"; satırında, JavaScript'in en eski değişken tanımlama mekanizması olan var ile bellekte bir yer ayrılır. Bu yapı, motor tarafından kodun en tepesine taşınma (hoisting) özelliğine sahiptir.
Bellek Güncellemesi:sehir = "İstanbul"; komutu çalıştırıldığında, mevcut bellek adresindeki verinin üzerine yeni string ("İstanbul") yazılır. var, modern let yapısına benzer şekilde değer değişimine tam izin verir.
Fonksiyon Kapsamı:Analiz edildiğinde, bu değişkenin blok kapsamı ( { } ) yerine fonksiyon kapsamına sahip olduğu görülür. Motor, bu değişkeni kodun neresinde olursa olsun o fonksiyonun (veya globalin) genel bir parçası olarak yönetir.
var kullanırken en riskli durum, aynı değişkenin yanlışlıkla tekrar tanımlanabilmesidir. JavaScript bu duruma hata vermez, ancak bu büyük projelerde ciddi karışıklıklara yol açar:
var sehir = "İzmir"; // Hata vermez, eski değeri sessizce ezer!
Ayrıca var, "hoisting" adı verilen bir davranış sergiler. Değişken tanımlanmadan önce ona erişmeye çalışırsanız hata almak yerine undefined sonucuyla karşılaşırsınız, bu da beklenmedik mantıksal hatalara (bug) neden olur.
Güncel JavaScript standartlarında (ES6+) artık var kullanımı önerilmemektedir. Bunun yerine daha güvenli olan let veya const tercih edilmelidir.
Scope Farkındalığı:var fonksiyon kapsamlıdır (function-scoped), oysa let ve const blok kapsamlıdır ( { } ). Daha kontrollü bir kod yapısı için blok kapsamlı değişkenleri kullanmayı alışkanlık haline getirin.
Eski Kodlarla Uyumluluk:Sadece çok eski tarayıcıları desteklemeniz gereken projelerde veya miras (legacy) kodları düzenlerken var ile karşılaşabilirsiniz. Yeni başladığınız tüm projelerde modern standartlara sadık kalın.
const siteAdi = "ByteOmi";
console.log(siteAdi);
let ziyaretciSayisi = 1;
ziyaretciSayisi = 2;
console.log(ziyaretciSayisi);
Bu örnek, sabit değerler ile değişken değerlerin bir arada kullanımını gösterir. siteAdi bilgisi bir marka ismidir ve çalışma süresince değişmemesi gerekir; bu nedenle const ile tanımlanmıştır.
ziyaretciSayisi ise sürekli artabilen dinamik bir veridir. let kullanımı, bu verinin başlangıçta 1 olup daha sonra 2 değerine güncellenmesine imkan tanır.
JavaScript motoru kodları yukarıdan aşağıya doğru işler. İlk olarak sabit ismi belleğe kaydeder, ardından değişkeni tanımlar ve değerini bir artırarak güncel sonuçları konsola yansıtır.
const siteAdi = "ByteOmi"; satırında, bellek üzerinde değiştirilemez bir referans oluşturulur. "ByteOmi" katarı bu referansa bağlanır; bu aşamadan sonra siteAdi tanımlayıcısına yeni bir değer atanması motor seviyesinde engellenir.
Dinamik Bellek Tahsisi:let ziyaretciSayisi = 1; komutu ile let anahtar kelimesi kullanılarak yeniden atamaya izin veren bir bellek alanı ayrılır. Başlangıçta tam sayı tipindeki 1 değeri bu adrese ilklendirilir (initialization).
Değer Mutasyonu ve Çıktı Akışı:ziyaretciSayisi = 2; satırında, mevcut referans adresi korunarak içerisindeki veri 2 değeri ile güncellenir. Program akışı (execution flow) boyunca console.log metotları, bu bellek adreslerindeki o anki güncel durumları standart çıktı birimine (konsol) iletir.
Bu koddaki en kritik hata riski, yanlışlıkla siteAdi değerini değiştirmeye çalışmaktır. Sabit bir değişkene yeni değer atamaya kalktığınızda şu hatayı alırsınız:
TypeError: Assignment to constant variable.
Ayrıca, değişkenleri tanımlarken tırnak işaretlerini unutmak (Örn: ByteOmi yerine tırnaksız yazmak) JavaScript'in bunu bir değişken ismi sanmasına ve tanımlı bulamadığında ReferenceError fırlatmasına neden olur.
Modern geliştirmede altın kural şudur: Her şeyi const ile tanımlayın, eğer değerin gerçekten değişmesi gerekiyorsa o zaman let'e dönüştürün.
Mantıksal Ayrım:Kodunuzu okuyan diğer geliştiriciler const gördüğünde bu değerin asla değişmeyeceğini bilir. Bu, kodun okunabilirliğini ve güvenilirliğini ciddi oranda artırır.
Veri Güvenliği:Sabit veriler için const kullanmak, yanlışlıkla veri ezilmesini önleyen bir güvenlik bariyeridir. Özellikle büyük ölçekli projelerde bu alışkanlık bug sayısını azaltır.
let kullaniciAdi = "Mehmet";
let skor1 = 50;
console.log(kullaniciAdi);
console.log(skor1);
// Yanlış Kullanım Örneği:
// let 1kullanici = "Ahmet"; // ❌ Sayı ile başlayamaz
// let kullanici adi = "Ayşe"; // ❌ Boşluk olamaz
// let skor = 10;
// let Skor = 20; // ⚠ Bunlar farklı değişkenlerdir
Bu örnek, JavaScript'te geçerli ve geçersiz değişken isimlendirmelerini karşılaştırır. Geçerli isimlendirmelerde kullaniciAdi örneğindeki gibi harf ile başlamak ve kelimeleri birleşik yazmak esastır.
Değişken isimleri rakam içerebilir ancak rakamla başlayamaz. skor1 geçerli bir kullanımken, rakamın başta olması JavaScript motoru tarafından anlaşılamaz.
JavaScript "case-sensitive" (büyük/küçük harf duyarlı) bir dildir. Bu, skor ve Skor isimli iki değişkenin bellekte tamamen farklı kutucuklar olarak tutulduğu anlamına gelir.
Örnek içerisinde ki let kullaniciAdi satırında JavaScript motoru, isimlendirmeyi alfabetik bir karakterle başladığı için geçerli kabul eder. Bellekte bu etiket için bir alan ayırır ve "Mehmet" katarını (string) bu alana depolar.
Sayısal Karakter Kullanımı:Örnek içerisinde ki let skor1 = 50; ifadesinde, rakamın ismin sonunda yer alması dilin sözdizimi kurallarına uygundur. Motor, bu tanımlayıcıyı tararken hata fırlatmaz ve sayısal (number) tipindeki veriyi başarıyla atar.
Büyük/Küçük Harf Duyarlılığı (Case-Sensitivity):Kodun yorum satırındaki skor ve Skor ayrımı, JavaScript'in her karakterin ASCII/Unicode değerini kontrol ettiğini gösterir. Bellek yönetim birimi, bu iki ismi farklı adreslere bağlanan benzersiz anahtarlar (unique keys) olarak değerlendirir.
Değişkeni sayı ile başlatmak veya isimde boşluk bırakmak programın çalışmasını durduran bir SyntaxError tetikler:
SyntaxError: Invalid or unexpected token
Boşluk kullanımı durumunda JavaScript, kullanici adi ifadesini iki ayrı komut sanır ve aradaki bağlantıyı kuramadığı için kodun geri kalanını okuyamaz.
Birden fazla kelimeden oluşan isimlerde kullaniciAdi örneğindeki gibi ilk harf küçük, sonraki kelimelerin ilk harfi büyük yazılmalıdır.
Özel Karakterler:İsimlerde boşluk yerine alt çizgi ( _ ) veya dolar işareti ( $ ) kullanabilirsiniz, ancak diğer sembollerden ( -, @, ! ) kaçınmalısınız.
Anlamlılık ve Dil:Değişken isimlerini projenin genel diline uygun (genellikle İngilizce veya tamamen Türkçe) ve içerdiği veriyi tam açıklayacak şekilde seçin.
const urunAdi = "Klavye";
let adet = 1;
let fiyat = 250;
console.log("Ürün: " + urunAdi);
console.log("Toplam Tutar: " + (adet * fiyat));
adet = 2;
console.log("Yeni Toplam Tutar: " + (adet * fiyat));
// Kullanıcı ürün sayısını artırdığında sadece adet değişkeni değişir, hesaplama otomatik güncellenir.
Bu senaryoda ürün ismi sabittir (const), ancak adet ve fiyat gibi veriler değişkenlik gösterebileceği için let ile tanımlanmıştır. Kodun gücü, matematiksel işlemlerin değişken isimleri üzerinden yapılmasından gelir.
adet * fiyat işlemi sırasında JavaScript, bellekteki güncel sayısal değerleri alır ve sonucu hesaplar. adet = 2; ataması yapıldığında, sonraki hesaplamalar otomatik olarak yeni değer üzerinden gerçekleşir.
"Ürün: " + urunAdi gibi kullanımlar, metin ile değişkenin değerini uç uca ekleyerek kullanıcıya anlamlı bir çıktı sunar. Bu işleme "birleştirme" denir.
Kodun başlangıcında const belirleyicisi ile urunAdi referansı oluşturulur. Motor, bu etiketi bellekteki "Klavye" katarına bağlar. Hemen ardından let ile adet ve fiyat isminde iki farklı değiştirilebilir hücre tahsis edilerek sayısal veriler ilklendirilir.
Aritmetik Değerlendirme ve Tip Dönüşümü:console.log içerisindeki ifadesi, motor tarafından öncelikli olarak işlenir. Hesaplanan sayısal sonuç, artı (+) operatörü ile metinsel bir katarla birleştirilir (implicit coercion); bu sayede karmaşık bir veri yapısı standart bir çıktı metnine dönüştürülür.
Durum Güncelleme (State Update):adet = 2; satırı icra edildiğinde, motor adet referansının işaret ettiği adrese gider ve eski veriyi (1) yeni veriyle (2) değiştirir. Sonraki toplama işlemi çağrıldığında, motor güncel bellek durumunu sorgular ve yeni katsayı üzerinden hesaplamayı yeniden gerçekleştirerek çıktı birimine iletir.
İşlem sırasında parantez kullanımına dikkat edilmelidir. Parantez olmazsa JavaScript bazen metin birleştirme ve matematiksel önceliği karıştırabilir; bu durum hatalı sonuçlara veya NaN çıktısına yol açabilir.
console.log("Toplam: " + adet * fiyat); // Parantezsiz riskli olabilir.
Ayrıca urunAdi sabit olduğu için onu urunAdi = "Mouse" şeklinde değiştirmeye çalışmak programın çökmesine neden olan bir TypeError üretir.
Modern kodda artı (+) işareti yerine backtick (` `) kullanarak `${urunAdi}` şeklinde yazım yapmak çok daha temiz bir görünüm sağlar.
Veri Tipi Güvenliği:Fiyat gibi parasal değerlerde her zaman sayısal tip kullanın. Eğer veriler tırnak içinde ("250") gelirse, matematiksel işlemler hatalı sonuçlar verebilir.
Otomasyon Odaklılık:Hesaplamaları doğrudan değişken isimleri üzerinden kurgulayarak, kodun farklı yerlerinde aynı değeri elle (hardcoded) yazmaktan kaçının; bu sayede bakım maliyetini düşürürsünüz.
// Değişmeyecek bilgiler
const kullaniciAdi = "Mehmet";
const dogumYili = 2000;
// Değişebilecek bilgiler
let yas = 2026 - dogumYili;
let girisSayisi = 1;
console.log("Kullanıcı: " + kullaniciAdi);
console.log("Yaş: " + yas);
console.log("Giriş Sayısı: " + girisSayisi);
// Kullanıcı tekrar giriş yapıyor
girisSayisi = girisSayisi + 1;
console.log("Yeni Giriş Sayısı: " + girisSayisi);
Bu kod yapısında, bir kullanıcının asla değişmeyecek olan dogumYili verisi const ile korunurken, her yıl güncellenmesi gereken yas bilgisi matematiksel bir işlemle ( 2026 - dogumYili ) hesaplanmıştır.
Daha önce incelediğimiz "sayaç mantığı" burada girisSayisi üzerinde uygulanmıştır. Kullanıcı sisteme her giriş yaptığında, mevcut değer bellekte çağrılır, üzerine 1 eklenir ve yeni değer değişkene tekrar atanır.
Değişkenlerin ve sabitlerin bir arada kullanımı, verilerin hem güvenliğini sağlar hem de uygulamanın etkileşimli bir şekilde güncellenmesine olanak tanır.
const kullaniciAdi ve const dogumYili ifadeleriyle bellekte salt-okunur alanlar tahsis edilir. Bu değerler, programın yürütme ömrü (runtime) boyunca bellekteki adreslerinde sabitlenir ve herhangi bir üzerine yazma girişimi motor tarafından engellenir.
Dinamik İfade Değerlendirmesi:let yas = 2026 - dogumYili; satırında motor, önce sağ taraftaki aritmetik ifadeyi işler. Bellekteki sabit dogumYili değerini çağırır, çıkarma işlemini tamamlar ve çıkan sonucu yas için ayrılan dinamik bellek hücresine atar.
Kümülatif Veri Güncelleme:girisSayisi = girisSayisi + 1; komutu icra edilirken; motor mevcut hücredeki değeri okur, işlemcide aritmetik artışı gerçekleştirir ve yeni veriyi aynı bellek adresine geri yazar. Bu işlem, değişkenin durumunu (state) bir önceki aşamaya bağlı olarak güncelleyen klasik bir "increment" sürecidir.
yas hesaplanırken kullanılan dogumYili değişkeni eğer tanımlanmamış olsaydı veya yanlış yazılsaydı, işlem sonucunda NaN ( Sayı Değil ) hatası alınırdı.
let yas = 2026 - dogumYili; // dogumYili const olmasaydı veya tanımlanmasaydı hata oluşurdu.
Unutulmamalıdır ki; const ile tanımlanan bir sabiti, sayaç gibi artırmaya çalışmak (dogumYili++) çalışma zamanı hatasına (TypeError) neden olur.
Yaş gibi zamanla değişen verileri elle yazmak yerine, bu örnekteki gibi bir referans noktası (doğum yılı) üzerinden hesaplatmak, kodun her yıl manuel olarak güncellenmesi gerekliliğini ortadan kaldırır.
Artırma Operatörleri:girisSayisi = girisSayisi + 1 yerine, modern JavaScript'te daha profesyonel bir duruş sergileyen girisSayisi++ veya girisSayisi += 1 kısayolları kullanılmalıdır.
Veri Kaynağına Güven:Sabitlerinizi kodun en üstünde gruplandırarak tanımlamak, projenin okunabilirliğini artırır ve hangi verilerin "temel taş" olduğunu netleştirir.
Değişken Tanımlama Kuralları ve İsimlendirme Prensipleri ECMAScript Söz Dizimi ve Semantik Yaklaşım
JavaScript'te bir değişken tanımlama süreci, dilin temel kurallarını belirleyen ECMAScript (ECMA-262) Standardı tarafından kesin çizgilerle belirlenmiştir.
Söz Dizimi ( Syntax ): Bir programlama dilinin söz dizimi, o dildeki ifadelerin ve komutların yazılma biçimini, yani dilbilgisini ifade eder.
JavaScript motorunun kodunuzu hatasız bir şekilde okuyup ( parse ) yürütebilmesi için, tanımladığınız her değişken adının bu kurallara tam olarak uyması zorunludur.
Aksi takdirde motor, kodun çalışmasını durduran bir SyntaxError fırlatır.
Teknik KısıtlamalarTeknik olarak geçerli bir değişken adı oluşturmak için şu katı kurallara uyulmalıdır:
- Başlangıç Karakteri: Bir değişken adı yalnızca bir harf ( a-z, A-Z ), alt çizgi (_) veya dolar işareti ($) ile başlayabilir. Kesinlikle rakamla başlayamaz.
- İzin Verilen Karakterler: İlk karakterden sonra, isim içinde harfler, rakamlar (0-9), alt çizgiler ve dolar işaretleri kullanılabilir.
- Büyük/Küçük Harf Duyarlılığı (Case Sensitivit):
JavaScript büyük ve küçük harflere duyarlıdır.
elma, Elma ve ELMA bellekte tamamen farklı üç değişkeni temsil eder. - Yasaklı Kelimeler (Reserved Keywords): Dilin kendisine ait olan özel kelimeler ( if, for, function, class, return) değişken adı olarak kullanılamaz.
Zorunlu kuralların ötesinde, kodun zamanla gelişimi ve ekip çalışmasına uygunluğu açısından, kodun okunabilirliğini artıran isimlendirme prensiplerine uymak bir gerekliliktir:
- CamelCase Kullanımı: JavaScript topluluğunda standart olarak, ilk kelimenin küçük, sonraki kelimelerin baş harfinin büyük yazıldığı camelCase yapısı benimsenmiştir ( kullaniciAdi, toplamFiyat ).
- Anlamlı İsimlendirme: Değişken adları, içerdikleri veriyi net bir şekilde tanımlamalıdır. x veya y gibi belirsiz isimler yerine, musteriYasi gibi açıklayıcı isimler kullanılmalıdır.
Söz Dizimi (Syntax) Kuralları (Zorunlu) Motorun Kodu Ayrıştırması İçin Mutlak Gereklilikler
Bunlar, kodun JavaScript motoru tarafından doğru bir şekilde ayrıştırılmas ve yürütülmesi için mutlak suretle uyulması gereken kurallardır.
İzin Verilen Karakterler: Değişken adları sadece belirli bir karakter setini içerebilir.
Bunlar; İngilizce alfabesindeki harfler ( a-z, A-Z ), rakamlar ( 0-9 ), alt çizgi ( _ ) veya dolar işaretidir ( $ ).
Bu setin dışındaki özel karakterler ( %, , -, @ vb. ) değişken isminde kullanılamaz.
Başlangıç Kuralı: Değişken isimlendirmesinde en kritik kısıtlama başlangıç karakteridir.
Değişken adları, kesinlikle bir rakamla (0-9) başlayamaz.
Bu kısıtlama, derleyicinin sayısal değerler ile değişken isimlerini ayırt edebilmesi için gereklidir.
Ancak isimler, bir alt çizgi, dolar işareti veya herhangi bir harf ile başlayabilir ( _sayac, $deger, v1 ).
Case SensitivityJavaScript büyük/küçük harfe duyarlı bir dildir.
Bu, aynı kelimenin farklı yazımlarının motor tarafından tamamen farklı varlıklar olarak algılanması demektir.
urunAdi, UrunAdi ve urunadi ifadeleri, motor tarafından üç farklı değişken olarak algılanır ve bellekte üç ayrı adreste saklanır.
Bu kurala dikkat edilmemesi, "tanımlanmamış değişken" hatalarının en yaygın sebebidir.
Yasaklı Kelimeler ve BoşluklarAyrılmış Anahtar Kelimeler (Reserved Keywords): JavaScript'in kendi yapısını ve komutlarını tanımlayan özel kelimeler değişken adı olarak kullanılamaz.
function, if, for, while, let, const, var, class gibi kelimeler dilde önceden tanımlı işlevlere sahiptir ve değişken ismi olarak atanmaları söz dizimi hatasına yol açar.
Boşluk Yasağı: Değişken adları tek bir bloktan oluşmalıdır ve içinde boşluk karakteri barındıramaz.
Motor, boşluğu komutun bitişi veya yeni bir parametre başlangıcı olarak algılar.
Çok kelimeli isimler için boşluk bırakmak yerine CamelCase gibi birleştirme stilleri kullanılmalıdır.
|
Stil Adı
|
Açıklama
|
Kullanım Örneği
|
Kullanım Alanı
|
|---|---|---|---|
|
Camel Case
(Deve Notasyonu)
|
JavaScript topluluğunda değişkenler, fonksiyonlar ve
metotlar için en yaygın kullanılan
stildir.
İlk kelimenin ilk harfi küçük, sonraki kelimelerin ilk harfleri büyük yazılır. Modern JavaScript geliştirmede standart kabul edilir ve tüm büyük framework'lerde ( React, Vue, Angular ) bu stil tercih edilir. |
"kullaniciAdi", "toplamUrunSayisi",
"hesaplaToplam()", "getKullaniciBilgisi()" gibi değişkenler için
kullanılır.
|
Değişkenler, Fonksiyonlar, Metotlar,
Obje Özellikleri, Event
Handler'lar
|
|
Pascal Case
|
Her kelimenin ilk harfi büyük yazılır.
JavaScript'te bu stil, genellikle sınıf ( class ) isimleri veya kurucu fonksiyonlar için ayrılmıştır. React, Vue gibi framework'lerde bileşen (component) isimleri için de kullanılır. |
"UrunDetay", "KullaniciYonetimi",
"SiparisOlustur",
React.Component gibi sınıf isimleri için kullanılır.
|
Sınıflar, Bileşenler,
Kurucu Fonksiyonlar, TypeScript Interface'leri
|
|
Snake Case
(Yılan Notasyonu)
|
Kelimeler birbirinden alt çizgi (_) ile ayrılır ve genellikle tamamen küçük harf kullanılır.
JavaScript'te nadiren kullanılsa da, bazı eski kütüphanelerde veya veri tabanı alan isimlerinde görülebilir. Python ve Ruby gibi dillerde yaygın olarak kullanılır, ancak JavaScript'te modern standart değildir. |
"toplam_urun_sayisi", "kullanici_adi",
"veri_tabani_baglantisi" gibi veri tabanı alan isimleri için kullanılır.
|
Veri Tabanı Alan İsimleri, API Response Alanları,
Eski Kütüphaneler, Nadir Durumlar
|
|
UPPER_SNAKE_CASE
|
Tüm harfler büyük yazılır ve kelimeler alt çizgi ile
ayrılır.
Bu stil, değeri kodun yürütülmesi boyunca hiç değişmeyecek olan sabitleri (constants) tanımlamak için kullanılır. Genellikle dosyanın en üstünde veya ayrı bir config dosyasında tanımlanır ve tüm uygulama boyunca kullanılır. |
"PI_SAYISI", "MAX_DENEME_SAYISI",
"API_BASE_URL", "DEFAULT_TIMEOUT" gibi sabit değerler için
kullanılır.
|
Global Sabitler (const),
Konfigürasyon Değerleri, Enum Benzeri Yapılar,
Magic Number'ların Yerine
|
|
Stil Adı
|
Pratik Kullanım Senaryoları
|
Kod Örnekleri
|
|---|---|---|
|
Camel Case
|
Değişken
Tanımlama: Kullanıcı adı, ürün fiyatı, toplam tutar gibi günlük değişkenler için.
Fonksiyon İsimlendirme: Hesaplama, veri çekme, doğrulama gibi işlevsel fonksiyonlar için. Event Handler'lar: onClick, onSubmit, onChange gibi kullanıcı etkileşimleri için. Obje Metotları: getKullanici(), setUrun(), hesaplaToplam() gibi metodlar için. |
let kullaniciAd = "Ahmet";
function hesaplaToplam() { ... } const urunFiyati = 100; |
|
Pascal Case
|
Sınıf Tanımlama:
Kullanıcı, Ürün, Sipariş gibi entity sınıfları için.
React Bileşenleri: UserProfile, ProductCard, OrderList gibi component'ler için. TypeScript Interface: IUser, IProduct gibi tip tanımlamaları için. Kurucu Fonksiyonlar: new User(), new Product() gibi constructor çağrıları için. |
class UrunDetay { ... }
function KullaniciYonetimi() { ... } const UserCard = () => { ... }; |
|
Snake Case
|
API Response:
Backend'den gelen JSON verilerinde alan isimleri için.
Veri Tabanı: SQL sorgularında veya ORM mapping'lerinde kolon isimleri için. Eski Kod Tabanları: Legacy projelerde veya eski kütüphanelerde görülebilir. Python/Ruby Entegrasyonu: Bu dillerle çalışırken uyumluluk için kullanılabilir. |
const response = { "user_name" : "Ahmet" };
SELECT total_price FROM orders; const veri_tabani = { ... }; |
|
UPPER_SNAKE_CASE
|
Matematiksel
Sabitler: PI, E, MAX_VALUE gibi değişmeyen matematiksel değerler için.
Konfigürasyon: API URL'leri, timeout değerleri, limit'ler gibi ayarlar için. Enum Benzeri Yapılar: Durum kodları, hata mesajları, tip tanımları için. Magic Number Önleme: Kod içinde tekrar eden sayısal değerlerin anlamlı isimlerle değiştirilmesi için. |
const PI_SAYISI = 3.14159;
const API_BASE_URL = "https://api.example.com"; const MAX_RETRY_COUNT = 3; |
JavaScript Değişken Türleri: var, let ve const Kapsam, Değişmezlik ve ES6 Devrimi
JavaScript'te değişken tanımlama mekanizması, dilin evrimi boyunca önemli ölçüde değişime uğramıştır.
Bu değişim, programlama dilinin en temel özelliklerinden biri olan kapsam ve değişmezlik kavramlarını daha güvenli ve öngörülebilir hale getirme çabasının sonucudur.
Modern yazılım mühendisliği, kodun sadece çalışmasını değil, aynı zamanda hataya kapalı olmasını talep eder.
Bu bağlamda, değişkenlerin nerede yaşadığı ve değerinin korunup korunmadığı kritik bir mimari karardır.
Fonksiyon Kapsamı ve HoistingJavaScript'in başlangıcından itibaren kullanılan var anahtar kelimesi, değişken yönetiminde bazı karmaşıklıklara ve potansiyel hatalara yol açan davranışlara sahipti.
Temel Sorunlar: Özellikle Hoisting ( değişkenin tanımlanmadan önce çağrılabilmesi ancak değerinin undefined olması ) ve sadece Fonksiyon Kapsamına ( Function Scope ) sahip olması ( blokları yoksayması ), büyük projelerde değişkenlerin birbirini ezmesine neden olabiliyordu.
Bu durum, modern yazılım mühendisliği prensipleriyle ve diğe dillerin disipliniyle çelişiyordu.
Blok Kapsamı ve Hassas KontrolBu sorunları gidermek ve dili daha olgun hale getirmek amacıyla, ES6 standardıyla birlikte let ve const anahtar kelimeleri tanıtıldı.
Bu yeni anahtar kelimeler, değişkenlerin sadece Blok Kapsamına ( Block Scope ) ( yani süslü parantezler {} arasına ) sahip olmasını sağlayarak kapsam sızıntılarını önlemiştir.
Ayrıca, değişkenin değerinin sonradan değiştirilip değiştirilemeyeceği konusunda kesin kurallar koyarak geliştiricilere çok daha hassas bir kontrol sunmuştur.
Bu bölümde, her üç anahtar kelimenin teknik farklılıklarını ve modern JavaScript'te hangi durumlarda tercih edilmeleri gerektiğini detaylıca inceleyeceğiz.
Var Anahtar Kelimesi: Tarihsel Kullanım ve Teknik Dezavantajlar Fonksiyon Kapsamı ve Hoisting Sorunları
var, ES6 standardı öncesinde JavaScript'te değişken tanımlamak için kullanılan tek anahtar kelimeydi.
Dilin ilk on yılını aşkın süresince tek değişken tanımlama yöntemi olması nedeniyle büyük bir tarihsel öneme sahiptir.
Ancak, modern ve ölçeklenebilir JavaScript kodunda kullanımı genellikle önlenir ve önerilmez.
Bunun temel nedeni, dilin temel mantığı olan kapsam ve yaşam döngüsü ( lifecycle ) konularında yarattığı öngörülemez davranışlardır.
Fonksiyon Kapsamı (Function Scoping)var ile tanımlanan değişkenler Fonksiyon Kapsamına sahiptir.
Bu, değişkenin sadece tanımlandığı fonksiyonun içinde erişilebilir olduğu anlamına gelir.
Blokları Yoksayma: Diğer birçok programlama dilinin aksine, var değişkenleri if blokları, for döngüleri veya while döngüleri gibi süslü parantezlerle ( {} ) tanımlanan kod bloklarının içindeki kapsamı yoksayar.
Bu durum, bir döngü içinde tanımlanan değişkenin döngü bittikten sonra da dışarıdan erişilebilir olmasına ve potansiyel olarak başka bir değişkenle karışmasına veya onun değerini ezmesine neden olur, bu da yan etkilere yol açar.
Bildirim Öncesi Erişim Riskivar'ın bir diğer teknik dezavantajı da Hoisting ( Yukarı Çekilme ) özelliğidir.
Hoisting Tanımı: var ile tanımlanan bir değişken, kodun yürütülmesinden önce motor tarafından fiziksel olarak tanımlandığı fonksiyonun veya global kapsamın en üstüne taşınır, ancak sadece bildirimi taşınır, atanan değeri değil.
Sonuç olarak, değişken tanımlanmadan önce bile çağrılabilir, ancak değeri bu noktada otomatik olarak undefined olur.
Bu durum, kodun okunduğu sırada ne anlama geldiği ile gerçekten ne yaptığı arasında bir kopukluk yaratarak, hataların tespitini zorlaştırır.
|
Özellik
|
Açıklama
|
Akademik/Teknik Detay
|
|---|---|---|
|
Kapsam Türü
|
Fonksiyon Kapsamlıdır, var ile tanımlanan değişkenler,
tanımlandıkları blok ( bir if veya
for döngüsü ) yerine, bulundukları fonksiyonun tamamında
erişilebilirdir.
Eğer bir fonksiyon içinde değillerse, global kapsama dahil olurlar. |
Bu durum, yazılımcıların beklediği blok kapsamından
(Block
Scope) farklıdır ve özellikle döngü
değişkenlerinin ( for döngüsündeki i ) fonksiyon dışından erişilebilir olmasına neden olarak
kapsam karmaşası yaratır.
|
|
Hoisting
|
var ile
tanımlanan
değişkenler, kodun yürütülmesinden önce
motor tarafından fiziksel olarak
kapsamlarının en üstüne taşınır.
|
Motor, sadece değişkenin tanımını (var x;) yukarı taşır,
değer atamasını (x = 10;) taşımaz.
Bu, değişkenin tanımlandığı satırdan önce çağrılmasına olanak tanır, ancak değeri o an için undefined olur. |
|
Yeniden Tanımlanabilirlik
|
Aynı kapsam içinde aynı isimle birden fazla var değişkeni
tanımlanabilir.
|
Motor, ikinci tanımlamayı görmezden gelir ve yalnızca
değer atamasını günceller. Bu, tipik
olarak hata veren bir durum olmasına rağmen JS motoru burada sessiz kalır.
|
|
Özellik
|
Modern JavaScript'teki Etkisi
|
|---|---|
|
Kapsam Türü
|
Kapsam Sızıntısı: Büyük kod tabanlarında beklenmedik yan
etkilere ve hatalara
yol açan yaygın bir hatadır.
|
|
Hoisting (Yukarı Çekme)
|
Öngörülemezlik: Kodun akışını takip etmeyi zorlaştırır ve
değişkenin neden
tanımsız olduğunu anlamayı güçleştirir.
|
|
Yeniden Tanımlanabilirlik
|
Çakışma Riski: Büyük ekiplerde veya farklı modülleri
birleştirirken, aynı
isimle tanımlanan değişkenlerin birbirini ezmesine ve beklenmeyen değer değişikliklerine neden
olur.
|
Neden Modern JavaScript'te Kullanımından Kaçınılmalıdır? Kapsam Sızıntıları, Güvenlik Açıkları ve Modülerlik İhlali
var anahtar kelimesi, doğası gereği kapsam sızıntılarına neden olur.
Bir döngü veya koşul bloğu içinde tanımlanan değişkenin, o bloğun dışına taşarak genel kapsamı kirletmesi, yazılım mühendisliğinin temel ilkeleri olan modülerlik ( parçaların birbirinden bağımsız olması ) ve kapsülleme ( verinin korunması ) prensipleriyle doğrudan çelişir.
Bu durum, büyük ölçekli uygulamalarda değişkenlerin yanlışlıkla birbirini etkilemesine ve takibi zor hatalara yol açar.
Sessiz Hata RiskiEn tehlikeli özelliklerinden biri de aynı isimle tekrar değişken tanımlamaya izin vermesidir.
Modern dillerde, aynı kapsamda aynı isimli iki değişken tanımlamak genellikle bir hata sebebidir.
Ancak var, geliştiriciyi uyarmadan ikinci tanımlamayı kabul eder ve önceki değişkenin değerini sessizce ezer ve bu, kodun güvenilirliğini ciddi şekilde zedeler.
Let ve Const StandartlaşmasıGünümüzde bu sorunlu davranışlar, let ve const anahtar kelimelerinin sunduğu daha sıkı, öngörülebilir blok kapsamlı ve yeniden atama kısıtlamalı yapılarla tamamen çözülmüştür.
Bu nedenle var, çok eski tarayıcılara destek verme zorunluluğu ( legacy code ) gibi istisnai durumlar olmadığı sürece, yeni projelerde kesinlikle kullanılmamalıdır.
Modern JavaScript geliştirme standartları, varsayılan olarak const, değişkenlik gerektiğinde ise let kullanımını dikte eder.
// Hoisting Örneği
console.log(deger); // Çıktı: undefined (değişken hoist edildi ama değeri henüz atanmadı)
var deger = 10;
console.log(deger); // Çıktı: 10
// Yeniden Tanımlama Örneği
var x = 5;
console.log(x); // Çıktı: 5
var x = 10; // Yeniden tanımlama mümkün
console.log(x); // Çıktı: 10
JavaScript motoru, var ile tanımlanan değişkenleri kodun en tepesine "asansör" gibi çeker. Bu yüzden değişken henüz tanımlanmadan çağrıldığında hata vermek yerine undefined çıktısını verir.
Yeniden Tanımlama:
var anahtar kelimesi,
aynı kapsamda aynı isimle defalarca değişken oluşturulmasına izin verir.
Kodda gördüğünüz var x = 10; satırı, daha önce tanımlanmış olan x değişkenini
sessizce ezer.
Bu davranışlar JavaScript'in esnekliğini gösterse de, değişkenlerin nerede ve nasıl değiştiğini takip etmeyi zorlaştırdığı için modern yazılım dünyasında birer risk olarak kabul edilir.
JavaScript motoru, kodun yürütülmesinden önce (creation phase) var anahtar kelimesini tarar. var deger bildirimini (declaration) kodun en üstüne taşır (hoist) ve bellekte yer ayırır. Ancak atama işlemi (assignment) satırına gelene kadar bu adres undefined değeriyle ilklendirilir; bu yüzden ilk console.log hata fırlatmaz.
Yeniden Bildirim (Redeclaration) Mekanizması:
var x = 5; satırından sonra tekrar
var x =
10; yazıldığında, motor bu durumu bir hata olarak görmez. Aynı kapsam içerisinde
mevcut olan
x referansını bulur ve bellekteki eski veriyi sessizce yeni tam
sayı
(integer) değeri olan 10 ile günceller.
Program, bellek hazırlık aşamasından sonra yukarıdan aşağıya doğru icra edilir. Her console.log() metodu çağrıldığında, motor o andaki bellek yığınını (stack) sorgulayarak en güncel veriyi standart çıktı birimine aktarır. Yeniden tanımlama özelliği, bellek yönetim biriminde yeni bir adres açmak yerine mevcut adresi manipüle etmeye devam eder.
var ile yapılan en büyük hata, değişkenin değerinin "hoisting" nedeniyle yanlışlıkla ezilmesidir. JavaScript bu durumlarda bir hata fırlatmaz (Silent Fail), ancak uygulama içinde beklenmedik sonuçlara yol açar.
// Mantıksal Risk:
var kullanici = "Ali";
// ... yüzlerce satır sonra ...
var kullanici = "Ayşe"; // JavaScript uyarmaz, Ali verisi kaybolur.
Eğer bu örneği let ile deneseydik, ikinci kez tanımlama yaparken bir SyntaxError alarak hatamızı anında fark edebilirdik.
Öngörülebilirlik: Hoisting gibi kafa karıştırıcı durumlardan kaçınmak için değişkenlerinizi her zaman kullanmadan önce tanımlayın ve modern projelerde var yerine let veya const kullanın.
Sessiz Hatalara Dikkat: Yeniden tanımlama özelliğine güvenerek kod yazmak, projeniz büyüdüğünde değişken isimlerinin çakışmasına neden olur. Bir ismin tek bir amaç için kullanıldığından emin olun.
Eski/Yeni Ayrımı: Bu örneği öğrenmek, eski (legacy) projeleri okurken "neden bu değişken tanımlanmadan önce hata vermiyor?" sorusuna teknik bir yanıt vermenizi sağlar.
// Fonksiyon Kapsamlılık Örneği
function ornekVarKapsam() {
if (true) {
var mesaj = "Merhaba Dünya";
console.log(mesaj); // Çıktı: Merhaba Dünya
}
console.log(mesaj); // Çıktı: Merhaba Dünya (if bloğunun dışında da erişilebilir)
}
ornekVarKapsam();
// console.log(mesaj); // Hata: mesaj is not defined (fonksiyon dışında erişilemez)
var ile tanımlanan bir değişken, tanımlandığı fonksiyonun tamamında geçerlidir. Örnekte görüldüğü üzere, mesaj değişkeni bir if bloğu içinde oluşturulmasına rağmen, o bloğun dışından da erişilebilir durumdadır.
Bu durum, var anahtar kelimesinin Blok Kapsamı özelliğine sahip olmamasından kaynaklanır. JavaScript motoru, fonksiyon içindeki herhangi bir yerde tanımlanan var değişkenini, o fonksiyonun en tepesine kadar görünür kılar.
Ancak bu esneklik fonksiyonun sınırlarında biter. Fonksiyon dışında mesaj değişkenine erişmeye çalışmak, değişkenin bellekteki "yaşam alanının" dışına çıkmak anlamına gelir.
var mesaj bildirimi bir if bloğu içerisinde yapılmış olsa da, JavaScript motoru bu değişkeni bağlı olduğu en yakın fonksiyon olan ornekVarKapsam'ın genel faaliyet alanına (scope) dahil eder. Bu teknik süreç, değişkenin blok sınırlarını aşarak fonksiyonun her yerinden erişilebilir olmasını sağlar.
Blok Sızıntısı (Scope Leakage):Kodun icrası sırasında, motor if (true) bloğunu işleyip dışarı çıktığında mesaj değişkenini bellekten temizlemez (garbage collection yapmaz). var anahtar kelimesi blok kapsamı (block-level scoping) özelliğine sahip olmadığı için, veriyi fonksiyonun bitimine kadar bellekte canlı tutmaya devam eder.
Yürütme Sınırları ve İstisna Yönetimi:Fonksiyon dışındaki console.log(mesaj); çağrısında motor, mesaj tanımlayıcısını global kapsamda arar. Değişken sadece fonksiyonun yerel bellek yığınında (local stack) tanımlandığı ve fonksiyon tamamlandığında bu yığın yok edildiği için, motor referansı bulamaz ve ReferenceError istisnasını tetikler.
Fonksiyonun dışında console.log(mesaj); satırını çalıştırmaya kalktığınızda, JavaScript bu ismi tanımlı bulamaz ve programı durduran bir hata fırlatır:
ReferenceError: mesaj is not defined
var'ın blok dışına sızması (leak), döngülerde veya koşullu ifadelerde yanlışlıkla aynı isimli başka bir değişkenin değerini değiştirmenize neden olarak "mantıksal bug"lara yol açabilir.
Blok Kapsamını Tercih Edin: Değişkenlerin sadece tanımlandıkları süslü parantezler { } içinde kalmasını istiyorsanız, var yerine mutlaka let veya const kullanmalısınız.
Kapsülleme (Encapsulation): Değişkenlerin etki alanını dar tutmak, kodun güvenliğini artırır. Bir değişkenin işi bittiğinde bellekte erişilemez olması, kazara veri değişimlerini önler.
Modern Yaklaşım: Günümüzde var kullanımı, bu sızma davranışı nedeniyle profesyonel ekipler tarafından "anti-pattern" (kaçınılması gereken yöntem) olarak değerlendirilir. Her zaman blok kapsamlı modern alternatifleri tercih edin.
Let Anahtar Kelimesi: Blok Kapsamlı ve Kontrollü Değişken Yönetimi ES6 Standardı: Güvenlik ve Öngörülebilirlik
let, ES6 standardı ile JavaScript'e eklenmiş, var'ın temel yapısal dezavantajlarını
( fonksiyon kapsamlılık ve kontrolsüz yeniden tanımlama izni ) gidermek üzere tasarlanmış modern bir değişken tanımlama yöntemidir.
let, özellikle döngülerde, koşullu bloklarda ve modüler kod yapılarında güvenilirliği ve öngörülebilirliği esas alır.
Değeri zamanla değişebilecek veriler için ( sayaçlar, geçici değerler vb. ) güncel standarttır.
Süslü Parantezlerin Gücület'in en ayırt edici özelliği, Blok Kapsamına ( Block Scope ) sahip olmasıdır.
Çalışma Mantığı: Bir let değişkeni, yalnızca tanımlandığı süslü parantezlerin { ... } arasında yaşar ve erişilebilir olur.
Bu blok bir if koşulu, bir for döngüsü veya basitçe çıplak bir blok olabilir. Bloğun dışına çıkıldığında, değişken bellekten silinir ve erişilemez hale gelir.
Bu özellik, değişkenlerin global kapsamı kirletmesini ( scope pollution ) ve beklenmedik veri çakışmalarını kesin olarak önler.
Hata Önleme Mekanizmasıvar'ın aksine, let aynı kapsam içinde aynı isimle ikinci bir değişken tanımlanmasına izin vermez.
Eğer aynı blok içinde let x = 5; ve ardından let x = 10; yazarsanız, JavaScript motoru kodun çalışmasını durdurur ve bir SyntaxError fırlatır.
Bu katı kural, geliştiricilerin yanlışlıkla değişkenlerin üzerine yazmasını engelleyen önemli bir güvenlik katmanıdır.
Hoisting Davranışındaki Farklet değişkenleri de teknik olarak yukarı taşınır (hoisted), ancak var'dan farklı olarak başlangıç değeri atanmaz.
Değişken tanımlandığı satıra gelene kadar, o değişkene erişmeye çalışmak ReferenceError hatası verir.
Tanımlama ile bloğun başlangıcı arasındaki bu erişilemez bölgeye Temporal Dead Zone ( Geçici Ölü Bölge ) denir.
Bu, geliştiriciyi "tanımlamadan önce kullanma" hatasından korur.
|
Özellik
|
Açıklama
|
|---|---|
|
Kapsam Türü (Scope)
|
Blok Kapsamlıdır (Block
Scoped).
Değişken, sadece tanımlandığı en yakın kod bloğu ( {...} parantezleri ) içinde erişilebilirdir. Bloğun dışından erişilemez, bu da kapsam sızıntısını önler. |
|
Hoisting ve TDZ
|
let değişkenleri de motor tarafından hoist edilir ancak
Temporal Dead Zone (TDZ) mekanizmasına
sahiptir.
|
|
Yeniden Tanımlama
|
Yeniden Tanımlanamaz.
Aynı kapsam ( blok ) içinde aynı isimle birden fazla let değişkeni tanımlanamaz. |
|
Yeniden Atama
|
Yeniden Atanabilir.
Değişkenin değeri, tanımlandıktan sonra aynı tipte veya farklı tipte yeni bir değerle güncellenebilir. |
|
Akademik/Teknik Detay
|
var'a Göre İyileştirme
|
|---|---|
|
Bu, yazılımcıların if, for, while gibi
yapıların içinde tanımlanan değişkenlerin dışarıdan
erişilemeyeceğini varsaydığı tipik davranışa uyar.
|
Fonksiyon kapsamlı var'ın aksine, kapsam karmaşası ve
yan etkileri
ortadan
kaldırır.
|
|
TDZ, değişkenin
tanımlandığı satıra fiziksel olarak
gelinene kadar erişilmesini engeller.
Tanımlanmadan önce erişim denemesi, undefined yerine ReferenceError hatası fırlatır. |
Güvenilirlik: var'ın
yarattığı kafa karıştırıcı undefined hatasını engeller.
Değişkenin, sadece değer ataması yapıldıktan sonra kullanılmasını zorunlu kılar.
|
|
Bu kurala uyulmadığında motor hemen SyntaxError hatası
döndürür.
|
Tutarlılık: Büyük kod tabanlarında ad çakışmalarını ve
beklenmedik değer
ezilmelerini
önleyerek kodu daha sağlam (robust) hale getirir.
|
|
Bu özellik, döngü sayaçları, kullanıcı girişi veya
sürekli güncellenen durum bilgileri gibi
değişkenliği amaçlanan değerler için idealdir.
|
Bir değişkenin dinamik olarak değişebilmesi gerektiği
durumlarda
temel kullanım
tipidir.
|
Kullanım Alanı ve Felsefi Önemi Değişkenlik, Yerellik İlkesi ve Bakım Kolaylığı
let, değeri programın akışı içinde güncellenmesi, yeniden hesaplanması veya değiştirilmesi gereken tüm değişkenler için modern JavaScript'te önerilen standart anahtar kelimedir.
Döngü sayaçları (i , j k), anlık durum takibi yapan bayraklar ( flags ) veya matematiksel işlem biriktiricileri ( accumulators ) gibi zamanla farklı değerler alacak veri noktaları için let kullanımı zorunludur.
Locality Principlelet'in sunduğu Blok Kapsamı ve TDZ gibi teknik mekanizmalar, aslında derin bir programlama felsefesi olan "Yerellik" ( Locality ) ilkesini destekler.
Felsefe: Bu ilke, bir değişkenin sadece ihtiyaç duyulduğu en yakın yerde var olmasını ve sadece o kod bloğu içinde anlam ifade etmesini savunur.
Bir değişkenin yaşam döngüsü ne kadar kısaysa ve kapsamı ne kadar darsa, o değişkenin programın geri kalanı üzerindeki yan etki riski o kadar azdır.
Bilişsel Yükü AzaltmaBu yaklaşım, modüler ve kolay bakımı yapılabilir kod yazımını teşvik eder.
Geliştirici, let ile tanımlanmış bir değişkeni gördüğünde, o değişkenin etkisinin sadece ilgili blokla sınırlı olduğunu bilir.
Bu, kod okurken geliştiricinin zihninde tutması gereken bilgiyi ( bilişsel yükü ) azaltır ve hata ayıklama süreçlerini hızlandırır.
// Blok Kapsamlılık Örneği
function ornekLetKapsam() {
if (true) {
let mesaj = "Merhaba Dünya";
console.log(mesaj); // Çıktı: Merhaba Dünya
}
// console.log(mesaj); // Hata: mesaj is not defined (if bloğunun dışında erişilemez)
}
ornekLetKapsam();
// Temporal Dead Zone (TDZ) Örneği
// console.log(degerLet); // Hata: Cannot access 'degerLet' before initialization (TDZ nedeniyle)
let degerLet = 20;
console.log(degerLet); // Çıktı: 20
// Yeniden Tanımlama ve Yeniden Atama Örnekleri
let y = 10;
console.log(y); // Çıktı: 10
// let y = 20; // Hata: Identifier 'y' has already been declared (yeniden tanımlanamaz)
y = 30; // Yeniden atama mümkün
console.log(y); // Çıktı: 30
var'dan farklı olarak let, tanımlandığı süslü parantezlerin { } dışına sızmaz. Bu sayede if bloğu içinde oluşturulan bir değişken, o blok bittiği an bellekten silinir ve dışarıdan erişilemez hale gelir.
Hoisting ve TDZ:let ile tanımlanan değişkenler de teknik olarak yukarı çekilir (hoisted) ancak atama yapılana kadar Temporal Dead Zone (Geçici Ölü Bölge) içinde kalırlar. Bu bölgedeyken değişkene erişmeye çalışmak, `var`'daki gibi `undefined` döndürmek yerine hata fırlatır.
Atama Serbestliği:let, aynı ismi tekrar tanımlamanıza izin vermezken, mevcut değişkenin değerini dilediğiniz zaman güncelleyebilmenize olanak tanır.
let mesaj bildirimi, if bloğunun süslü parantezleri { } içerisinde bir leksikal çevre (lexical environment) oluşturur. JavaScript motoru, blok dışına çıkıldığı anda bu referansı bellekten (stack) temizler; bu nedenle blok dışındaki erişim denemeleri ReferenceError istisnası ile sonuçlanır.
Geçici Ölü Bölge (Temporal Dead Zone):let degerLet bildirimi kodun en üstüne çekilse de (hoisting), motor bu adresi ilklendirme (initialization) satırına kadar erişime kapatır. Bu "yasaklı bölge", değişkenin bellekte var olduğu ancak henüz değer atanmadığı (uninitialized) kritik süreci temsil eder ve kodun daha güvenli çalışmasını sağlar.
Yeniden Tanımlama Denetimi:let ile yapılan bildirimlerde, motor aynı isimli bir etiketin mevcut kapsamda (scope) daha önce kaydedilip edilmediğini kontrol eder. Eğer etiket bellekte zaten rezerve edilmişse, motor yürütmeyi durdurarak bir sözdizimi hatası fırlatır; ancak değer güncelleme (re-assignment) işlemlerinde mevcut bellek hücresindeki verinin değiştirilmesine izin verir.
Tanımlamadan önce değişkene erişmeye çalışırsanız, TDZ mekanizması nedeniyle şu kritik hatayı alırsınız:
ReferenceError: Cannot access 'degerLet' before initialization
Ayrıca, aynı kapsamda let y = 20; gibi bir satırla değişkeni tekrar tanımlamaya çalışmak, Identifier 'y' has already been declared hatasına yol açar. Bu, kazara değişken ezilmelerini önleyen harika bir güvenlik duvarıdır.
Önce Tanımla, Sonra Kullan: TDZ hatalarından kaçınmak için değişkenlerinizi her zaman kod bloğunun en başında tanımlamayı bir standart haline getirin.
Veri Sızıntısını Önle: Sadece belirli bir blokta (döngü, koşul) kullanacağınız veriler için let kullanarak global kapsama gereksiz yük bindirmeyin.
Net Ayrım: Değeri asla değişmeyecek veriler için const, sadece güncellenmesi gereken sayaç veya durum verileri için let kullanarak niyetinizi net bir şekilde belli edin.
Const Anahtar Kelimesi: Sabitlik ve Güvenli Referans Yönetimi Değişmezlik İlkesi ve Referans Bütünlüğü
const ( constant/sabit kısaltması ), ES6 ile tanıtılan ve programlama felsefesinde değişmezlik ilkesini en güçlü şekilde destekleyen anahtar kelimedir.
const, değeri kodun yürütülmesi boyunca sabit kalması gereken ve kasıtlı olarak değiştirilmemesi hedeflenen değişkenleri tanımlamak için kullanılır.
Bu, okuyucuya şu net mesajı verir: "Bu değişkenin taşıdığı değer, yaşam döngüsü boyunca güvenilirdir ve değişmeyecektir."
Katı Tanımlama Kurallarıconst kullanımı, var ve let'e göre çok daha katı kurallara tabidir:
- Zorunlu İlk Atama: const ile bir değişken tanımladığınız anda, ona bir başlangıç değeri atamak zorundasınız. const pi; şeklinde boş bir tanımlama yapmak, anında SyntaxError ile sonuçlanır.
- Yeniden Atama Yasağı: Tanımlandıktan sonra, const değişkenine yeni bir değer atanamaz. pi = 3.15; gibi bir girişim, çalışma zamanında TypeError ( Tip Hatası ) fırlatır.
const hakkında en çok yanlış anlaşılan konu, onun değerin kendisini dondurduğu sanrısıdır.
Oysa teknik gerçek şudur: const, değerin kendisini değil, o değere giden referansı ( bellek adresini ) sabitler.
Bu ayrım, İlkel Türler ve Referans Türleri arasında kritik bir fark yaratır:
- Sayılar veya Stringler gibi ilkel türlerde değer değiştirilemez.
- Ancak bir Dizi veya Nesne const ile tanımlandığında, değişkenin gösterdiği "kutu" değiştirilemez ama kutunun içindeki içerik değiştirilebilir.
Yani; const list = []; tanımlamasından sonra list.push(1) yapılabilir ( içerik değişir ), ancak list = [1, 2] yapılamaz
( referans değişimi yasaktır ).
|
Özellik
|
Açıklama
|
|---|---|
|
Kapsam Türü (Scope)
|
Blok Kapsamlıdır (Block
Scoped). Tıpkı let gibi, tanımlandığı en yakın
kod
bloğu ({...}) içinde
geçerlidir.
|
|
Hoisting ve TDZ
|
Temporal Dead Zone
(TDZ) mekanizmasına sahiptir.
Tanımlanmadan önce erişim, ReferenceError
hatasına
yol açar.
|
|
Yeniden Tanımlama
|
Yeniden Tanımlanamaz.
Aynı kapsamda aynı isimle birden fazla const tanımlamak SyntaxError hatasına neden olur. |
|
Yeniden Atama
|
Yeniden Atanamaz.
Bir const değişkenine ilk atama yapıldıktan sonra, değeri değiştirilemez. |
|
Teknik Detay ve Zorunluluk
|
Felsefi Katkısı
|
|---|---|
|
Bu, var'ın neden
olduğu global kapsam kirliliğini tamamen
önler ve değişkenin yerel kalmasını
sağlar.
|
Modülerlik: Değişkenin, sadece dar bir alanda geçerli
olmasını
sağlayarak kodun
modüler yapısını destekler.
|
|
Zorunluluk: const
değişkenleri tanımlanırken mutlaka bir
başlangıç değeri ile başlatılmalıdır
(const PI; geçersizdir).
|
Güvenilirlik: Sabit bir değerin asla tanımsız (undefined) durumda olmamasını
garanti
altına alır.
|
|
let ile aynı
sıkı
kuralı paylaşarak ad çakışmalarını
engeleler.
|
Tutarlılık: Kod tabanında isimlendirme bütünlüğünü korur.
|
|
Bu, const'un
temel
ve ayırt edici özelliğidir. Yeniden
atama denemesi TypeError hatası verir.
|
Değişmezlik: Kodun akışını tahmin etmeyi kolaylaştırır ve
değişkenin değerinin
yanlışlıkla değişmesini engeller.
|
Referans Tipi Değerler ve const Paradoksu Sabit Adres, Değişken İçerik
const'un davranışının akademik düzeyde incelenmesi gereken en önemli ve kafa karıştırıcı kısmı, Referans Tipi değerlerle
( Nesneler ve Diziler ) kullanıldığı zamandır.
Teknik Gerçek: const ile bir nesne veya dizi tanımlandığında, bellekte sabitlenen ( dondurulan ) şey verinin kendisi değil, değişkenin o veriyi bulmak için tuttuğu bellek adresidir ( referansıdır ).
Yani, const anahtar kelimesi değişkene şu emri verir:
"Hayatın boyunca sadece bu adresi (bu kutuyu) işaret edeceksin, asla başka bir kutuyu göstermeyeceksin."
Mutasyon ve ManipülasyonAncak, referansın işaret ettiği evin içi ( nesnenin özellikleri veya dizinin elemanları ) tamamen değiştirilebilir durumdadır, buna Mutasyon (Mutation) denir.
Örneğin: const ile tanımlanmış bir araba nesnesinin rengini değiştirebilirsiniz ( araba.renk = "kırmızı" ), çünkü bu işlem değişkenin tuttuğu ana bellek adresini değiştirmez, sadece o adresteki verinin bir parçasını günceller.
Kritik SınırlarBu paradoksu netleştirmek için sınırlar şöyledir:
- YASAK (Reassignment): const
liste = [1, 2];
dedikten sonra liste = [3, 4]; diyemezsiniz.
Bu, değişkeni yeni bir adrese yönlendirme girişimidir ve TypeError verir. - SERBEST (Mutation): liste.push(3); veya liste[0] = 9;
diyebilirsiniz.
Bu, mevcut adresteki dizinin içeriğini günceller ve const kuralını ihlal etmez.
Not: Eğer bir nesnenin içeriğinin de tamamen değiştirilemez olmasını istiyorsanız, const yeterli değildir; bunun için Object.freeze() gibi ek yöntemler kullanılmalıdır.
|
Durum
|
İşlem
|
Sonuç
|
Açıklama
|
|---|---|---|---|
|
const
|
const ayarlar = {};
ayarlar = {yeni: 'değer'}; |
Hata verir. ( TypeError hatası alınır.)
|
Değişkenin referansı değiştirilmeye çalışıldı, bu
yasaktır.
|
|
İçerik Değişimi
|
const ayarlar = {hiz: 10};
ayarlar.hiz = 20; |
Başarılı olur. ( const
kuralını ihlal etmez. )
|
Nesnenin içeriği değiştirildi, referans aynı kaldı, bu
izinlidir.
|
Ne Zaman const Kullanılmalı? Varsayılan Tercih ve Modern Best Practices
Modern JavaScript geliştirme pratiğinde, bir değişken tanımlarken varsayılan seçenek her zaman const olmalıdır.
Strateji: Kod yazarken zihniyet şu olmalıdır: "Aksi ispatlanana kadar her şey sabittir."
Geliştiriciler, ancak ve ancak değişkenin değerinin ilerleyen satırlarda değişmesi gerektiğinden emin olduklarında
( bir döngü sayacı veya birikimli toplam ) let'e geçiş yapmalıdır.
Kodun ÖngörülebilirliğiGeliştiriciler, kodun daha öngörülebilir ve hatasız olması için genellikle bir değeri değiştirmeyecekleri durumlarda const kullanmalıdır.
Bilişsel Yükü Azaltma: Bir kodu okuyan başka bir geliştirici, const ile tanımlanmış bir değişken gördüğünde, zihinsel olarak
"Bu değer kodun geri kalanı boyunca aynı kalacak, bunu takip etmeme gerek yok" diyerek rahatlayabilir.
Bu, kodun okunabilirliğini artırır ve bilişsel yükü ( cognitive load ) azaltır.
|
Kullanım Alanı
|
Kod Örneği
|
|---|---|
|
Matematiksel ve Evrensel Sabitler
|
const PI_SAYISI = 3.14159;
|
|
Yapılandırma Ayarları
(Configuration)
|
const API_URL = "https://api.example.com";
|
|
Modül Referansları ve Bağımlılıklar
|
const fs = require('fs');
const React = require('react'); |
|
Amaç ve Felsefe
|
Açıklama
|
|---|---|
|
Matematiksel değerler veya fiziksel kurallar
( yerçekimi katsayısı gibi ) evrensel gerçeklerdir ve programın çalışma süresi boyunca değişmeleri mantıken imkansızdır. |
Sihirli Sayılardan Kaçış:
Kodun içinde rastgele yerlerde 3.14159 sayısını kullanmak yerine, bunu isimlendirilmiş bir sabite atamak kodun okunabilirliğini artırır. Geliştirici kodu okurken "Bu sayı da ne?" diye sormaz, "Ah, bu Pi sayısıymış" der. Büyük Harf Konvansiyonu: Yazılım dünyasında, değeri derleme öncesinde bilinen ve asla değişmeyecek olan bu tür "sert kodlanmış" (hard-coded) sabitler için genellikle UPPER_SNAKE_CASE ( tamamı büyük harf ve alt çizgi ) isimlendirme standardı kullanılır. |
|
Tek Kaynak Doğrusu (Single Source of Truth):
Bir uygulama genellikle sunucularla, veritabanlarıyla veya dış servislerle iletişim kurar. Bu adreslerin kodun yüzlerce farklı yerinde "string" olarak tekrar tekrar yazılması büyük bir risktir. |
Bakım Kolaylığı:
Eğer API adresi değişirse, const ile tanımlanmış merkezi bir yapı sayesinde sadece tek bir satırı güncellemek yeterli olur. Bu değişken, uygulamanın o anki "çalışma ortamını" temsil eder ve uygulama çalışırken dinamik olarak değişmesi beklenmez. |
|
Güvenlik ve Kararlılık:
Bir projeye harici bir kütüphane (Dosya Sistemi modülü fs) dahil ettiğinizde, bu kütüphaneyi temsil eden değişkenin kodun ilerleyen satırlarında yanlışlıkla başka bir şeye dönüşmesi (fs = 5;) felakete yol açar. |
Değişmez Araçlar:
İthal edilen modüller, geliştiricinin elindeki "araçlardır". Bir usta çalışırken çekicinin bir anda tornavidaya dönüşmesini istemez. const, bu araçların güvenliğini ve bütünlüğünü garanti altına alarak, uygulamanın belkemiğini korur. |
// Blok Kapsamlılık Örneği
function ornekConstKapsam() {
if (true) {
const ad = "Ayşe";
console.log(ad); // Çıktı: Ayşe
}
// console.log(ad); // Hata: ad is not defined (if bloğunun dışında erişilemez)
}
ornekConstKapsam();
Daha önce let örneğinde gördüğümüz sızdırmazlık kuralı const için de geçerlidir. Sabit bir veri olan ad, sadece tanımlandığı if bloğu içerisinde yaşar.
Bellek Yönetimi:JavaScript motoru, kod bloğu tamamlandığında bu sabit veriyi bellekten temizler. Bu durum, özellikle büyük projelerde değişkenlerin birbirine karışmasını önleyen ve performansı koruyan modern bir standarttır.
Sınırlar Dahilinde Erişim:Sabitlere sadece tanımlandıkları kapsama alanı içinden erişilebilir. Bu katı kural, var anahtar kelimesinin yarattığı "her yerden erişilebilirlik" karmaşasını tamamen ortadan kaldırır.
const ad bildirimi, if bloğunun süslü parantezleri { } ile çevrili alanda özel bir kapsülleme oluşturur. JavaScript motoru, bu sabiti fonksiyonun genel yığınından (stack) ziyade sadece bu bloğa özgü leksikal çevreye (lexical environment) kaydeder.
Bellek Yaşam Döngüsü (Reference Removal):Blok içindeki işlemler tamamlanıp yürütme akışı kapanış parantezine ulaştığında, motor bu bloğa ait tüm const referanslarını erişilemez olarak işaretler. Bu süreç, bellekte gereksiz yer kaplayan verilerin temizlenmesini sağlar; dolayısıyla blok dışındaki console.log çağrısı yapıldığında motor ilgili adresi bulamaz.
İstisna Tetikleme Mekanizması:Motor, kapsam dışı bir referansla karşılaştığında önce yerel, sonra fonksiyonel ve en son global çevreyi tarar. ad tanımlayıcısı hiçbir geçerli çevrede bulunamadığı için yürütme durdurulur ve standart bir ReferenceError istisnası (exception) fırlatılarak hata yönetimi başlatılır.
Bloğun dışında console.log(ad); komutunu çalıştırmaya çalışmak, JavaScript'in o veriyi hiç bulamamasına neden olur ve şu hatayı fırlatır:
ReferenceError: ad is not defined
Unutmayın: const ile tanımlanan bir veriyi hem bloğu dışında kullanamazsınız hem de daha önceki derslerimizde işlediğimiz üzere değerini sonradan değiştiremezsiniz.
Bir fonksiyonun veya döngünün sadece belirli bir kısmında kullanılacak yardımcı sabitleri o blok içinde const ile tanımlayarak kodunuzu daha güvenli hale getirin.
Okunabilirlik:Bir geliştirici kodunuzda bloğa özel tanımlanmış bir const gördüğünde, o verinin etki alanının sınırlı olduğunu ve başka hiçbir yerde aranmaması gerektiğini anında anlar.
Genel Kural: Değişkenlerinizi her zaman mümkün olan en küçük kapsamda ( narrowest scope ) tanımlayın. Bu alışkanlık, kazara oluşan veri çakışmalarını %90 oranında önleyecektir.
// Referans Tipi Değerler ve const
const kullanici = {
isim: "Can",
yas: 30,
};
console.log(kullanici); // Çıktı: { isim: 'Can', yas: 30 }
kullanici.yas = 31; // Nesnenin içindeki özellik değiştirilebilir
console.log(kullanici); // Çıktı: { isim: 'Can', yas: 31 }
// kullanici = { isim: "Deniz" }; // Hata: Assignment to constant variable (referans değiştirilemez)
const sayilar = [1, 2, 3];
console.log(sayilar); // Çıktı: [1, 2, 3]
sayilar.push(4); // Dizinin içine yeni eleman eklenebilir
console.log(sayilar); // Çıktı: [1, 2, 3, 4]
// sayilar = [5, 6]; // Hata: Assignment to constant variable (referans değiştirilemez)
const ile bir nesne (object) veya dizi (array) tanımladığınızda, sabitlenen şey verinin kendisi değil, o verinin bellekteki adresidir.
Bu nedenle, adres değişmediği sürece nesnenin içindeki bir özelliği (kullanici.yas) değiştirmek veya bir dizinin içeriğine yeni eleman eklemek (sayilar.push) tamamen mümkündür.
JavaScript motoru için önemli olan, değişkenin işaret ettiği "bellek kutucuğunun" başka bir yapıya yönlendirilmemesidir. İçerideki mutasyonlar (değişimler) bu kuralı bozmaz.
const kullanici tanımlandığında, JavaScript motoru nesne verisini belleğin Heap bölgesinde saklar ve bu verinin adresini değişkene bağlar. const kullanımı, sadece bu adresin değiştirilmesini (yeni bir nesne atanmasını) engeller; adresin işaret ettiği "kutunun" içindeki verilerin güncellenmesine kısıtlama getirmez.
Nesne ve Dizi Mutasyonu (Property Mutation):kullanici.yas = 31; veya sayilar.push(4); komutları icra edilirken, motor değişkenin referansını bozmaz. Sadece mevcut referans üzerinden ilgili bellek adresine giderek, nesnenin bir özelliğini veya dizinin bir indisini günceller. Bu işlem teknik olarak bir "atama" (assignment) değil, bir "mutasyon" sürecidir.
Referans Ezme Denetimi (Reference Re-assignment):Kodun yorum satırındaki sayilar = [5, 6]; denemesi yapıldığında, motor bellekte tamamen yeni bir dizi oluşturup bu yeni adresi mevcut değişkene atamaya çalışır. Değişken const ile mühürlendiği için, motor bu "adres değiştirme" talebini reddeder ve yürütmeyi durdurarak bir tip hatası fırlatır.
Eğer sabitlenmiş bir değişkeni tamamen yeni bir nesneye veya diziye atamaya çalışırsanız (Örn: sayilar = [5, 6]), referans değişeceği için şu hatayı alırsınız:
TypeError: Assignment to constant variable.
Bu hata, değişkenin işaret ettiği bellek adresini koruma altına alan const mekanizmasının bir sonucudur. İçerik değişebilir ama "kimlik" değişemez.
Teknik bir engel olmadıkça, tüm dizi ve nesne tanımlamalarınızda const kullanın. Bu, yapının yanlışlıkla tamamen sıfırlanmasını önler.
İçerik Koruması:Eğer nesnenin içindeki verilerin de değiştirilemez olmasını istiyorsanız, Object.freeze(nesneAdi) metodunu kullanarak tam koruma sağlayabilirsiniz.
Tutarlı Mimari:Referans tiplerle çalışırken adresin sabit kalması, bellek sızıntılarını ve karmaşık hata senaryolarını minimize ederek daha sağlam bir kod tabanı oluşturmanıza yardımcı olur.
Değişken Bildirme, Başlatma ve Yeniden Atama Kavramları var, let ve const Üzerindeki Davranışsal Farklılıklar
Programlamada değişkenler etrafında dönen üç temel işlem vardır: Bildirme ( Declaration ), Başlatma ( Initialization ) ve Yeniden Atama
( Reassignment ).
Bu kavramların var, let ve const anahtar kelimeleri üzerindeki farklı etkilerini anlamak, JavaScript'in değişken yönetim felsefesini tam olarak kavramak için hayati öneme sahiptir.
Değişkeni TanıtmaBildirme, JavaScript motoruna, kodun ilgili kapsamında o isimde bir değişkenin var olacağını bildirme eylemidir.
Bu işlem, bellekte değişkenin adı için bir yer ayrılmasını sağlar.
- Davranış Farkı: let
isim;
veya
var sayac; örnek
olarak düşünülürse var ve let
sadece
bildirilip bırakılabilir
( bu durumda değerleri undefined olur ), ancak const'un sadece bildirilmesi yasaktır; const bildirilirken aynı zamanda başlatılmalıdır.
Başlatma, bildirilen değişkene ilk defa bir değer atanmasıdır.
Bu, bellek adresine verinin fiziksel olarak yazılmasıdır.
- Örnek: let isim = "Ali"; ( Bildirme ve Başlatma tek adımda ) veya daha önce bildirilen bir değişkene ilk değer ataması.
- Davranış Farkı:Tüm anahtar kelimeler başlatılabilir.
Ancak, const için başlatma, bildirildiği satırda mutlak bir zorunluluktur.
Başlatılmazsa SyntaxError oluşur.
Yeniden Atama, daha önce başlatılmış bir değişkenin değerini daha sonraki bir kod satırında yeni bir değerle güncelleme işlemidir.
- Örnek: sayac = 10; ( Yeni bir anahtar kelime kullanılmaz. )
- var ve let: Yeniden atama serbesttir.
- const: Yeniden atama yasaktır.
Bir değer atandıktan sonra değiştirme girişimi TypeError ile sonuçlanır.
Yeniden Atama kavramından ayrı olarak, bir de Yeniden Bildirme kavramı vardır; yani aynı kapsamda aynı değişken adını tekrar kullanma girişimi.
- var: Aynı kapsamda yeniden bildirmeye izin verir ( sessizce önceki değeri ezer ).
- let ve const: Aynı
kapsamda
yeniden bildirmeye izin vermez ( Hata fırlatır ).
Bu, modern anahtar kelimelerin güvenilirlik açısından en önemli avantajıdır.
Bildirme (Declaration) Kapsam Kaydı ve Bellek Tahsisatı Talimatı
Bildirme (Declaration), bir değişkenin adının ( teknik terimle tanıtıcısının / identifier ), kodun ilgili kapsamı içinde resmen tanıtılması ve kullanıma hazır hale getirilmesi işlemidir.
Bu, basit bir isimlendirmeden öte, yasal bir süreçtir.
Programcı bu eylemle derleyiciye şu mesajı verir: "Bu kapsamda, bu isimde benzersiz bir değişken var olacaktır."
Eğer aynı kapsamda ( let/const için ) bu isim zaten kayıtlıysa, motor bildirme aşamasında işlemi reddeder.
Niyet ve Motor TalimatıDeğişken bildirimi, iki farklı boyutta ele alınabilir:
- Dilbilimsel Açı: Programcının niyetini ifade eder. Kodun okunabilirliği için bir varlığa isim verilmesidir.
- Teknik Açı: Yürütme anında JavaScript motoruna, programın ilerleyen süreçlerinde bu isim altında kullanılacak değer için bilgisayarın fiziksel belleğinde (Memory Heap veya Stack) mantıksal bir yer ayırma talimatını verir.
Bildirme aşaması, değişkenin değerinin ne olduğu sorusundan tamamen bağımsızdır, bu kritik aşamadır.
Bu işlem, yalnızca "bu isim var olacaktır" bilgisini programa yerleştirir.
Kutunun içine ne konulacağı ( Başlatma / Initialization ) sonraki adımdır.
Anahtar Kelime Etkisi: var, let ve const anahtar kelimelerinin her biri, bu bildirimi farklı kurallar ve kısıtlamalar altında gerçekleştirir.
Özellikle Hoisting ve Temporal Dead Zone (TDZ) mekanizmaları, bildirimin kodun hangi satırında "aktif" hale geleceğini belirleyen temel faktörlerdir.
|
Anahtar Kelime
|
Başlatma Durumu
|
Teknik Zorunluluk
|
|---|---|---|
|
var / let
|
Başlatma zorunlu değildir.
Başlatılmadığı takdirde varsayılan değeri undefined olur. |
Geliştirici tercihine bağlıdır, ancak let için genelde
başlatılması iyi bir pratiktir.
|
|
const
|
Başlatma zorunludur.
Bir const değişkeni, tanımlandığı an mutlaka bir başlangıç değeri almalıdır. |
Başlatılmadığı takdirde motor SyntaxError hatası verir.
Bu, const'un sabitlik felsefesinin temel gereğidir. |
// Değişken bildirimi ve başlatma aynı anda
let isim = "Ahmet";
const dogumYili = 1990;
// Değişken bildirimi, daha sonra değer ataması
let yas;
yas = 35;
console.log(yas); // Çıktı: 35
// Başlatılmamış değişkenler (let ve var) undefined değerini alır
let bosDegisken;
console.log(bosDegisken); // Çıktı: undefined
// const ile değişken tanımlanırken mutlaka başlatılmalıdır
// const sabit; // Hata: Missing initializer in const declaration
JavaScript'te bir değişkeni oluşturmaya "bildirim", ona ilk değerini vermeye ise "başlatma" denir. let yas; satırı sadece bir bildirimdir; değişken bellekte yer ayırır ancak henüz bir değere sahip değildir.
Varsayılan Değer:let veya var ile bildirilen ancak değer atanmayan değişkenler otomatik olarak undefined değerini alır. Bu, değişkenin var olduğunu ancak "tanımsız" olduğunu gösteren özel bir veri tipidir.
Zorunlu Başlatma:Değişmezlik ilkesi gereği const ile tanımlanan yapılar, oluşturuldukları an bir değerle başlatılmak zorundadır. Sabitlerin değeri sonradan atanamaz, bu yüzden "başlatılmamış bir sabit" kavramı JavaScript motoru için geçersizdir.
let yas; satırı icra edildiğinde, JavaScript motoru bellekte (stack) bir alan ayırır ancak bu alana herhangi bir somut veri bağlamaz. Bu aşamada tanımlayıcı, motor tarafından otomatik olarak undefined (tanımsız) veri tipiyle ilklendirilir. Bu, bellek adresinin rezerve edildiğini ancak henüz bir değerle eşleşmediğini (uninitialized) gösterir.
Gecikmeli Değer Atama (Late Binding):yas = 35; ifadesi çalıştırıldığında, motor daha önce rezerve edilen bellek adresine giderek undefined etiketini siler ve yerine 35 sayısal verisini yazar. Bu süreç, değişkenin yaşam döngüsü içerisinde bildirim ve atama aşamalarının birbirinden ayrılabileceğini kanıtlar.
Sabitlerde Sözdizimi Zorunluluğu:const belirleyicisi kullanıldığında, motor "atomik tanımlama" bekler. Yani bildirim ve ilklendirme işlemleri aynı satırda gerçekleşmelidir. Motor, const satırını tararken bir değer ataması görmezse, referansın daha sonra değiştirilemeyeceğini bildiği için yürütmeyi derhal durdurur ve bir SyntaxError fırlatır.
Sabit bir değişkeni değer atamadan bırakmaya çalıştığınızda (const sabit;), JavaScript motoru işlemi durdurur ve şu hatayı fırlatır:
SyntaxError: Missing initializer in const declaration
Bu hata, kodunuzun daha yazım aşamasında engellenmesini sağlayarak, ileride "tanımsız bir sabitle işlem yapma" gibi daha büyük mantıksal hataların önüne geçer.
Değişkenlerinizi her zaman bir başlangıç değeri ile oluşturmaya çalışın. Sayısal veriler için 0, metinler için boş tırnak ("") kullanmak, undefined kaynaklı hataları azaltır.
const Önceliği:Uygulama boyunca değişmeyecek referanslar veya yapılandırma ayarları için mutlaka const kullanın ve tanımlandığı satırda değerini netleştirin.
Temiz Kod:Değişken bildirimlerini fonksiyonların veya kod bloklarının en üstünde yaparak, hangi değişkenlerin o blok boyunca "yaşayacağını" ve başlangıç durumlarını diğer geliştiriciler için görünür kılın.
Yeniden Atama (Reassignment) Değer Güncelleme ve Mutability Felsefesi
Yeniden Atama, daha önce bildirilmiş ve genellikle bir başlangıç değeriyle başlatılmış olan bir değişkenin, tuttuğu mevcut değeri bırakıp yeni bir değerle güncellenmesi işlemidir.
Teknik Mekanizma: Bu işlem, sadece bir eşitlik değişikliği değildir; motorun değişkenin temsil ettiği bellekteki fiziksel konuma giderek, orada bulunan eski veriyi silmesi ( veya referansı koparması ) ve yerine yeni veriyi yazması anlamına gelir.
Bu yetenek, değişkenlerin programlama dillerindeki dinamizm ve değişebilirlik ( mutability ) felsefesini yansıtır.
Dinamik Durum YönetimiYeniden atama, statik bir veri deposu ile çalışan bir program arasındaki farkı yaratır.
Programın çalışma zamanında durumunu değiştirmesi, döngü sayaçlarını ilerletmesi ( i++ gibi ) veya kullanıcı girdilerine göre bilgileri güncellemesi için hayati önem taşır.
İmmutability ve GüvenlikModern JavaScript'te, let ve var yeniden atamaya izin verirken, const anahtar kelimesi yeniden atamayı kesinlikle yasaklar ve denemesi durumunda TypeError fırlatır.
Neden Kısıtlanır? Bu yasak keyfi değildir; özellikle değişmezlik prensiplerini uygulayan fonksiyonel programlama paradigmaları için kritik öneme sahiptir.
Bir değişkenin yeniden atanamayacağını bilmek, kodun daha öngörülebilir olmasını sağlar ve beklenmedik durum değişikliklerinden kaynaklanan yan etkileri ( side-effects ) azaltır.
Bu, güvenilir yazılım mühendisliğinin temel bir ilkesidir.
|
Anahtar Kelime
|
Yeniden Atama İzni
|
Felsefi Sonuç
|
|---|---|---|
|
var / let
|
Değişkenin değeri, bildirimden sonra herhangi bir zamanda
ve
herhangi bir sayıda
değiştirilebilir.
|
Bu esneklik, döngü sayaçları ve durum güncellemeleri için
gereklidir.
let ile yeniden atama, blok kapsamlı olduğu için var'a göre daha güvenlidir. |
|
const
|
Kesinlikle İzinli Değildir.
Yeniden atama denemesi TypeError hatası verir. |
İmmutability
ilkesini destekler.
Değişkenin referansının veya değerinin sabit kalacağını garanti eder. |
Akademik Açıdan Önem: Referans Tipleri ve const Tip Semantiği, Kimlik ve Durum Ayrımı
Yeniden atama konusunda const'un referans tiplerindeki davranışı, dilin tip semantiği açısından kritik bir akademik ayrım sunar.
Bu ayrım, JavaScript'in belleği nasıl yönettiğine dair derin bir kavrayış gerektirir. Temelde soru şudur:
"Sabitlenen şey verinin kendisi mi, yoksa verinin kimliği mi?"
İlkel Türler: number, string, booleanDeğer Tipi (Value Type): Sayılar, metinler ve mantıksal değerler gibi ilkel türlerde, verinin değeri ve kimliği bellekte ( Stack ) bütünleşiktir.
Bu nedenle, const ile tanımlanan bir değer tipi asla değiştirilemez.
Hem yeniden atama yasaktır hem de değerin kendi içinde değişmesi teknik olarak mümkün değildir; buradaki sabitlik mutlaktır.
Nesneler ve Diziler: object, arrayReferans Tipi (Reference Type): Nesneler ve dizilerde durum tamamen farklıdır.
const, sadece değişkenin bellekteki nesneye işaret eden okunu ( pointer / bellek adresi ) sabitler.
Akademik Sonuç: Bu, nesnenin içeriğinin ( özelliklerinin veya elemanlarının ) yeniden atanmaksızın değiştirilebileceği anlamına gelir.
const, işaretçinin yönünü dondurur ancak işaret edilen kutunun içini dondurmaz.
Kimlik vs. Durum (Identity vs. State)Bu davranış, const'un felsefesinin "Bu değişken her zaman aynı nesneyi işaret etmelidir." olduğu anlamına gelir.
Ancak o işaret edilen nesnenin içeriği dinamik olarak değişebilir.
Bu yaklaşım, büyük nesnelerin her küçük değişiklikte kopyalanıp yeniden oluşturulması yerine, mevcut bellek alanında güncellenmesine olanak tanıyarak performans verimliliği sağlar.
let sayi = 10;
console.log(sayi); // Çıktı: 10
sayi = 20; // Değer yeniden atandı
console.log(sayi); // Çıktı: 20
var mesaj = "Merhaba";
console.log(mesaj); // Çıktı: Merhaba
mesaj = "Hoşçakal"; // Değer yeniden atandı
console.log(mesaj); // Çıktı: Hoşçakal
Hem let hem de var, başlangıçta atanan değeri daha sonra değiştirmenize izin verir. Bu işlem sırasında bellekteki eski veri silinir ve yerine yeni veri (örneğin 10 yerine 20) yazılır.
Veri Tipi Bağımsızlığı:JavaScript'te bir değişkene yeniden değer atarken, yeni değerin sadece miktarı değil, içeriği de değişebilir. mesaj değişkeni başlangıçta selamlaşma içerirken, saniyeler içinde vedalaşma metnine dönüşebilir.
Akış Takibi:console.log() çıktıları, JavaScript'in kodu yukarıdan aşağıya işlediğini (procedural) kanıtlar. Aynı isimli değişken, kodun farklı satırlarında farklı değerler sergileyerek uygulamanın o anki durumunu temsil eder.
let sayi = 10; satırı
icra edildiğinde, motor bellekte sayısal
bir hücre
ayırır. Bir sonraki satırdaki
sayi = 20; komutu, mevcut
bellek
referansını
bozmadan sadece hücre içerisindeki veriyi günceller (overwrite). Bu durum, let ve var'ın dinamik yapısını
ve
bellekteki verinin yürütme zamanında (runtime) değiştirilebilirliğini kanıtlar.
var mesaj tanımlayıcısı üzerinden yapılan "Merhaba"dan "Hoşçakal"a geçiş işlemi, motor seviyesinde bir içerik değişimidir. JavaScript motoru, tırnak içerisindeki yeni katarı mevcut değişkene bağlayarak, önceki verinin çöp toplayıcı tarafından temizlenmesi için boşa çıkarılmasını sağlar.
Yordamsal Yürütme (Procedural Execution):Kodun yukarıdan aşağıya doğru ilerleyen akışı içerisinde, console.log() metotları belleğin anlık durumunu (snapshot) yakalar. Aynı değişken ismi kullanılmasına rağmen, atama operatörünün (=) tetiklendiği satırdan itibaren motorun çıktı birimine ilettiği veri referansı güncellenmiş olur.
Değer atama sırasında yapılan en yaygın hata, atama operatörü olan eşittir (=) sembolünü unutmaktır. Bu durumda JavaScript motoru değişkeni güncellemek yerine yeni bir komut bekler ve yazım hatası verir.
sayi 20; // SyntaxError: Unexpected number (Eşittir unutuldu)
Ayrıca, daha önce üzerinde durduğumuz üzere, eğer bu örnekteki değişkenler const ile tanımlanmış olsaydı, yeniden atama satırlarında TypeError alınırdı. let ve var bu hatayı es geçerek güncelliği sağlar.
Niyetinizi Belli Edin: Eğer bir verinin ileride mutlaka değişeceğini biliyorsanız (bir kullanıcının mesajı veya sepet tutarı gibi), modern standart olan let anahtar kelimesini tercih edin.
Tip
Tutarlılığı: JavaScript teknik olarak bir sayı değişkenine metin atamanıza izin verse de
(sayi = "Yirmi"), mantıksal hataları önlemek için değişkenin
başlangıçtaki
veri tipine sadık kalmaya çalışın.
Minimalizm: Gereksiz yere değer yeniden ataması yapmaktan kaçının. Her atama bellekte küçük bir işlem maliyeti yaratır; kodunuzu daha az değişken güncellemesiyle kurmak performansı ve okunabilirliği artırır.
JavaScript Kapsam Kavramı (Scope) Görünürlük, Yaşam Döngüsü ve Mimari İzolasyon
Programlamada Kapsam, bir değişkenin veya fonksiyonun kodun hangi bölgelerinden erişilebilir olduğunu belirleyen temel bir mimari prensiptir.
Basitçe kapsam şu soruya cevap verir: "Kodun bu satırında durduğumda, hangi değişkenleri görebilirim?"
Kaynak Yönetimi AnalojisiTıpkı bir şirkette departmanların sadece kendi dosyalarına erişmesi, ancak yönetimin her şeye erişebilmesi gibi; kapsam da kaynakların nerede geçerli olacağını tanımlar.
Bu izolasyon, bir fonksiyonun içindeki değişkenlerin, diğer bloklardaki aynı isimli değişkenlerle karışmasını önleyen bir güvenlik duvarı görevi görür.
Varoluş ve Bellek TemizliğiKapsam sadece "mekansal" değil, aynı zamanda "zamansal" bir kavramdır, bellek yönetimi ile doğrudan ilişkilidir.
Bir kapsamın içine girildiğinde değişkenler hayat bulur (bellekte yer ayrılır). Kapsamdan çıkıldığında ise bu değişkenler genellikle ölür (bellekten silinir).
Bu, JavaScript'in Garbage Collector ( Çöp Toplayıcı ) mekanizması için hayati önemdedir.
En Az Ayrıcalık İlkesiKapsamı doğru yönetmek, yazılım mühendisliğindeki En Az Ayrıcalık İlkesi'ni destekler.
Değişkenleri mümkün olan en dar kapsamda tutmak; tehlikeli ad çakışmalarını ( naming collisions ) önleyerek, kodunuzun
modüler ve yönetilebilir olmasını sağlar.
Global Kapsam (Global Scope) En Üst Seviye Erişim ve Evrensellik
Global Kapsam, bir JavaScript ortamındaki hiyerarşinin en üst seviye kapsamıdır.
Herhangi bir fonksiyonun, bloğun veya modülün içine yerleştirmediğiniz, doğrudan dosyanın ana gövdesine yazdığınız her değişken, otomatik olarak bu kapsama dahil olur.
Görünürlük: Bu alanda tanımlanan yapılar; kodun her yerinden (derin fonksiyonlardan, koşul bloklarından veya modüllerden) erişilebilirdir ve
manipüle edilebilir.
Window ve Global NesneleriTeknik olarak Global Kapsam, çalışma ortamına göre özel bir Global Nesne ile temsil edilir:
- Tarayıcılarda: Global kapsam window nesnesidir. ( var x = 10 dediğinizde aslında window.x oluşturursunuz).
- Node.js'de: Global kapsam global nesnesiyle yönetilir.
Global kapsamın her yerden erişilebilir olması büyük bir güç gibi görünse de, modern mühendislikte genellikle kaçınılması gereken bir durumdur.
Çakışma Riski: Farklı kütüphaneler aynı global ismi kullanırsa, biri diğerini ezer. Buna Global Kirlilik denir.
Bellek Yükü: Global değişkenler, uygulama kapatılana kadar bellekte kalır. Garbage Collector tarafından otomatik temizlenemedikleri için gereksiz kaynak tüketimine yol açarlar.
Global Kapsamın Teknik Özellikleri Window Nesnesi, Global Kirlilik ve Ortam Farklılıkları
Tarayıcı ortamında (Chrome, Firefox vb.), global kapsamı temsil eden fiziksel yapı window nesnesidir.
Bu nesne, tarayıcı penceresini ve tüm akışı kontrol eden en üst otoritedir.
Geleneksel Yapışma SorunuGeleneksel olarak, var ile tanımlanan global değişkenler, doğrudan window objesinin bir özelliği haline gelirdi.
Örnek: var isim = "Ahmet"; yazdığınızda, arka planda otomatik olarak window.isim oluşturulmuş olurdu.
Risk: Bu durum, kirliliğin temel kaynağıydı. Geliştiriciler window.name veya window.location gibi yerleşik API'lerle aynı isimde değişken tanımlarsa, tarayıcının çalışma mantığını bozabilirlerdi.
Kirliliği Önleyen İzolasyonModern let ve const ile tanımlanan global değişkenler, kodun her yerinden erişilebilir olsa da, window objesine özellik olarak eklenmezler.
Bu değişkenler, "Bildirimsel Ortam Kaydı" adı verilen izole bir yapıda tutulur.
Bu, tarayıcı API'leri ile çakışmayı önleyen kritik bir mimari iyileştirmedir.
Sunucu Tarafı Global: "global"Node.js ortamında window bulunmaz; yerine global nesnesi geçer.
Ancak Node.js'in modüler yapısı gereği, en üst seviyede tanımlanan değişkenler genellikle o modüle (dosyaya) özel kalır.
Bu, sunucu tarafı güvenliği ve izolasyon için hayati bir farktır.
Global Kapsamın Sakıncaları (Akademik Perspektif) Mimari Riskler, Kirlilik ve Bakım Maliyeti
Global kapsamın geniş erişilebilirliği, ilk bakışta kolaylık gibi görünse de; büyük yazılım sistemlerinde ciddi mimari sorunlara ve yönetilemez kod yapılarına yol açar.
Global değişkenler, farklı geliştiriciler tarafından yazılan modüllerde veya üçüncü taraf kütüphanelerde aynı adı taşıyan değişkenlerle kolayca çakışabilir.
Senaryo: Sizin config adında tanımladığınız global bir nesne, yüklediğiniz bir analiz kütüphanesinin değişkeniyle ezilebilir.
Bu durum, uygulamanın veri bütünlüğünü bozar; modüler programlama ve veri kapsülleme prensiplerine tamamen aykırıdır.
Sıkı Bağlılık (Tight Coupling)Bir fonksiyonun doğru çalışması için dışarıdaki bir global değişkene bağımlı olması, o fonksiyonun bağımsız bir birim olmasını engeller.
Taşınabilirlik Sorunu: Fonksiyonu başka bir projeye taşımak istediğinizde, bağımlı olduğu global ortamı da taşımanız gerekir.
Bu, kodun yeniden kullanılabilirliğini yok eder.
İzlenebilirlik SorunuGlobal bir değişkenin değeri kodun herhangi bir yerinde ve herhangi bir zamanda değiştirilebilir.
Değişken aniden yanlış bir değer aldığında, bu değişikliği yapan kod parçasını bulmak için tüm projeyi taramanız gerekebilir.
Bu duruma "uzaktan etki" ( action at a distance ) denir ve hata ayıklama maliyetini artırır.
Garbage Collection VerimsizliğiGlobal kapsamda tanımlanan değişkenler, uygulama veya web sayfası çalışmayı bitirene kadar bellekte kalır.
Yerel değişkenler işleri bittiğinde Çöp Toplayıcı tarafından temizlenirken, global olanlar root kabul edildiği için temizlenmez.
Bu, bellek sızıntılarına zemin hazırlar.
let globalDegisken = "Ben globalim";
function globalOrnek() {
console.log(globalDegisken); // Erişilebilir
}
globalOrnek();
console.log(globalDegisken); // Erişilebilir
Herhangi bir fonksiyonun veya süslü parantezin { } dışında tanımlanan değişkenler "global" kabul edilir. Bu değişkenler, kod dosyasının en üst seviyesinden en içteki fonksiyonuna kadar her yerden okunabilir ve değiştirilebilir.
Erişim Hiyerarşisi:globalOrnek fonksiyonu çalıştırıldığında, kendi içinde globalDegisken isminde bir tanım bulamazsa dışarıya (global alana) bakar. Bu zincirleme erişim sayesinde fonksiyon dışındaki veriyi başarıyla konsola yazdırır.
Kalıcılık:Global değişkenler, uygulama çalıştığı sürece bellekte kalmaya devam eder. Bu durum, verinin her yerden ulaşılabilir olmasını sağlarken aynı zamanda bellek yönetiminde dikkatli olunmasını gerektirir.
let globalDegisken herhangi bir blok veya fonksiyonun dışında tanımlandığı için motor tarafından en üst seviye leksikal çevreye (Global Lexical Environment) kaydedilir. Bu süreçte değişken, uygulamanın yürütme bağlamı (execution context) sonlanana kadar bellekte kalıcı bir referans noktası oluşturur.
Kapsam Zinciri Araması (Scope Chain Search):globalOrnek fonksiyonu icra edilirken, console.log içerisindeki değişken ismi önce fonksiyonun yerel yığınında (local stack) aranır. Tanımlayıcı yerelde bulunamadığı için motor "Kapsam Zinciri" (Scope Chain) üzerinden bir üst seviyeye çıkar ve global kayıt defterindeki referansa ulaşarak veri akışını sağlar.
Erişilebilirlik ve Bellek Ömrü:Fonksiyon çağrısı tamamlandıktan sonra bile globalDegisken'in fonksiyon dışında tekrar erişilebilir olması, verinin "global nesne" ile olan bağından kaynaklanır. Motor, bu tür değişkenleri "her zaman ulaşılabilir" olarak işaretlediği için, yığın temizleme işlemleri bu değişkenin referansını etkilemez.
Global değişkenlerle ilgili en büyük hata, "Değişken Çakışması"dır. Eğer bir fonksiyon içinde global değişkenle aynı isimde yeni bir değişken tanımlarsanız (Shadowing), fonksiyon içindeki kodlar dışarıdaki global veriye erişemez ve yerel olanı kullanır.
let globalDegisken = "Global";
function hataRiski() {
let globalDegisken = "Yerel"; // Global olan gizlendi!
console.log(globalDegisken); // Çıktı: Yerel
}
Ayrıca, global bir değişkenin değerini bir fonksiyon içinde yanlışlıkla değiştirmek, o değişkeni kullanan diğer tüm fonksiyonların da hatalı çalışmasına neden olan ve tespiti zor "yan etkilere" yol açar.
Sadece uygulamanın geneline hitap eden (tema ayarları, kullanıcı kimliği vb.) verileri globalde tutun. Mümkün olduğunca verileri fonksiyonlara parametre olarak gönderin.
İsimlendirme Standartı:Global değişkenlerinizi diğerlerinden ayırmak için bazen APP_CONFIG gibi tamamen büyük harf veya belirgin önekler kullanarak çakışma riskini minimize edin.
Kapsülleme:Kodunuzu büyüttükçe global değişkenler yerine nesneleri (objects) veya modülleri kullanarak verileri gruplandırın. Bu, kodun bakımını kolaylaştırır ve hata payını düşürür.
🧭 Opsiyonel Okuma Notu
Bilgilendirme: Bu bölüm, konuların arka planına ve düşünsel temellerine daha derin bir bakış sunmak amacıyla hazırlanmıştır.
- Matematiksel, tarihsel ve felsefî içerikler isteğe bağlı olarak okunabilir.
- Her bölümün içerik seviyesi ve yoğunluğu farklılık gösterebilir.
- Temel düzey kullanıcılar için zorunlu değildir, ileri düzey okuma niteliğindedir.
Programlamanın Temel Taşı: Değişken Kavramı ( Felsefi ve Tarihsel Açıklama )
Programlamada veriyi isimlendirme ihtiyacının nasıl doğduğunu ve bellek
yönetiminin
evrimini felsefi bir bakış açısıyla anlayın.
Değişkenlerin sadece birer kod satırı değil, dijital dünyada bilginin
sürekliliğini sağlayan temel mantık araçları olduğunu keşfedeceksiniz.
Programlamanın Temel Taşı: Değişken Kavramı Matematiksel Kökenler ve Dijital Soyutlama
Değişken kavramı, sadece bir kod parçası değil, programlamanın ve algoritmik düşüncenin merkezinde yer alan en temel soyut yapıdır.
Bir yazılımın "canlı" hissettirmesini sağlayan, dış dünyadan veri alıp buna tepki vermesini mümkün kılan yegane mekanizmadır.
Değişkenler olmasaydı, bilgisayarlar sadece önceden tanımlanmış sabit sonuçları gösteren gelişmiş hesap makinelerinden öteye gidemezdi.
Cebirden AlgoritmayaBu kavramın kökenleri bilgisayarlardan binlerce yıl öncesine, matematiğin ve mantığın derinliklerine uzanır.
Antik matematikçiler ( özellikle Harezmi ve Cebir ilmi ), henüz bilinmeyen veya değişebilecek bir değeri temsil etmek için semboller
( bugünkü \(x\) veya \(y\) ) kullanmaya başladıklarında, aslında modern değişken mantığının temelini atmışlardır.
O dönemde "bilinmeyeni bulmak" için kullanılan bu semboller, bilgisayar bilimlerinde "bilineni saklamak ve değiştirmek" amacıyla yeniden yorumlanmıştır.
Statik Makinede Dinamik YaşamBilgisayar bilimlerinin ortaya çıkmasıyla bu kavram, hem pratik veri yönetimi ihtiyacını karşılamak hem de evrensel değişimi modellemek için hızla evrimleşmiştir.
Bilgisayar donanımı fiziksel olarak "statik" devrelerden oluşur. Yazılım ise "dinamik" bir süreçtir.
İşte değişkenler, bu statik donanım üzerinde dinamik bir dünya simülasyonu oluşturmamıza olanak tanıyan araçlardır.
Onlar sayesinde, aynı kod bloğu, içine giren veriye ( değişkene ) bağlı olarak her seferinde farklı bir çıktı üretebilir.
Değişken Kavramının Tarihsel ve Felsefi Kökenleri Belirsizliği Yönetme Sanatı ve Herakleitos
Bir değişkenin hikayesi, sadece matematiksel bir notasyondan ibaret değildir; insanlığın belirsizliği ve nesneler arasındaki ilişkileri anlama çabasıyla paralel ilerlemiştir.
Değişken, soyut düşüncenin somutlaşmış halidir ve zihnimizdeki "genelleme" yeteneğinin en saf yansımasıdır.
İnsan zihni, tekil olaylardan sıyrılıp genel formüller oluşturabildiği an, değişken kavramını icat etmiştir.
"Değişmeyen Tek Şey Değişimdir"Bu kavramın felsefi derinliği, evrenin sabit mi yoksa sürekli bir akış halinde mi olduğu sorusuna dayanır.
Antik filozoflardan Herakleitos'un meşhur "Değişmeyen tek şey değişimdir" sözü gibi, değişken kavramı da matematiği durağanlıktan dinamizme taşımıştır.
Değişkenler, bir yapıyı sadece o anki değeriyle değil, olası tüm değerler kümesiyle ilişkilendirme gücü sunar.
Gerçek Dünyanın Dijital ModeliProgramlama bağlamında değişken, bu köklü felsefi temelin pratik bir uygulamasıdır.
Bir yazılım; müşteri adı veya hava durumu gibi gerçek dünya verilerini temsil etmek zorundadır.
Bu veriler sürekli güncellenir ve değişken, bilgisayar belleğinde bu dinamik bilgiyi depolamak için ayrılmış etiketli bir kutu görevi görerek, karmaşık sistemlerin matematiksel modellemesini mümkün kılar.
Soyutlama Aracı Olarak KodSonuç olarak değişken, insanlığın "bilinmeyeni bilme" arayışının bir ürünüdür.
Programlamadaki her let veya const tanımı, antik bir ilkenin dijital dünyalar yaratmamıza olanak tanıyan temel bir soyutlama aracına dönüştüğünü gösterir.
Antik Dönem ve Statik Gerçeklikler Geometrinin Hakimiyeti ve Değişmezlik Algısı
Değişken kavramının yolculuğunda başlangıç noktası, Antik Yunan dönemidir.
Ancak o zamanların matematik anlayışı, günümüzden oldukça farklıydı ve daha çok statik gerçekliklere odaklanıyordu.
Antik zihin için "sayı" kavramı, genellikle somut nesnelerin adediyle veya geometrik uzunluklarla sınırlıydı.
Sayılar, soyut birer kap değil, varlıkların kendisiydi.
Sabit Şekiller ve Değişmez DeğerlerAntik Yunan matematikçileri ( Öklid, Pisagor gibi) için sayılar ve geometrik şekiller ( daireler, üçgenler, kareler ) genellikle sabit ve değişmez değerler olarak ele alınırdı.
Matematik esas olarak, kesin oranları ve şekillerin ideal özelliklerini incelemeye odaklanmıştı.
Örneğin: Bir dairenin alanını hesaplarken bugün pi olarak bildiğimiz sabit oranlar kullanılırdı, ancak yarıçap ( r ) bir "değişken" olarak değil, o anki dairenin spesifik ve sabit bir özelliği olarak görülürdü.
Varlık Felsefesi: "Nedir?" SorusuBu dönemde matematikçilerin ilgisi "hareket" veya "sürekli değişim" gibi dinamik durumları modellemekten ziyade, "Nedir?" sorusuna cevap veren mükemmel ve belirli sonuçlara yönelmişti.
Bu nedenle, bir değeri alıp zamanla başka bir değere dönüşebilen, yani belirsizliği temsil eden modern bir "değişken" kavramına duyulan ihtiyaç henüz tam olarak ortaya çıkmamıştı.
Matematik, bu çağda evrendeki değişimi yönetme aracı değil, evrendeki değişmez ve ebedi kuralları kaydetme aracıydı.
Rönesans ve Sembolik Gösterimin Standartlaşması Viète, Descartes ve Analitik Geometri Devrimi
Değişken kavramının modern anlamını kazanması ve matematiksel bir araç olarak standartlaşması, 16. ve 17. yüzyıllarda, bilimsel aydınlanmanın yaşandığı Rönesans döneminde gerçekleşti.
Bu dönem öncesinde matematiksel problemler sözel olarak ifade edilirdi.
Rönesans ile birlikte matematikçiler, bilinmeyen nicelikleri temsil etmek için harfleri sistematik ve evrensel bir şekilde kullanmaya başladılar.
Bu, matematiğin kendi "alfabesine" kavuşmasıydı.
Genellemenin MimarlarıÖzellikle François Viète ve René Descartes gibi figürlerin çalışmaları bu durumu sağlamlaştırdı:
- François Viète: Sadece bilinmeyenleri değil, katsayıları da harflerle temsil ederek matematiksel genellemeyi başlattı. Bu, tek bir denklemi çözmek yerine bir denklem sınıfını (ax + b = 0) incelemeyi mümkün kıldı.
- René Descartes: Bugün kullandığımız modern notasyonu standartlaştıran isimdir.
En kritik ilerleme, Descartes'ın Analitik Geometriyi geliştirmesiydi.
Değişkenler sadece denklemler için değil, geometrik şekilleri soyut bir biçimde tanımlamak için kullanıldı.
Örneğin: Bir parabolün denklemini y = ax^2 + bx + c şeklinde ifade etmek, artık tek bir parabolü değil, evrendeki tüm parabollerin
genel yapısını tek bir satırda tanımlamayı sağlıyordu.
Bu sayede, geometri ve cebir arasında köprü kuruldu. Değişkenler, matematiksel düşünceye muazzam bir soyutlama yeteneği kazandırarak, her problem için sıfırdan başlamak yerine genel bir kuralı uygulamayı kolaylaştırdı.
Kalkülüs ve Değişimin Felsefesi (Dinamizm) Newton, Leibniz ve Hareketin Matematiği
Değişken kavramı, 17. yüzyılın sonlarında Isaac Newton ve Gottfried Wilhelm Leibniz'in diferansiyel ve integral kalkülüsü geliştirmesiyle tarihsel zirvesine ulaştı.
Kalkülüs, matematiği o güne kadarki durağanlığından çıkarıp, hareket ve sürekli değişim dünyasını modelleyebilen dinamik bir araca dönüştürdü. Artık matematik sadece "olanı" değil, "olmakta olanı" anlatıyordu.
Bağımlı ve Bağımsız DeğişkenlerBu yeni çerçevede değişkenler, değişimin kendisini temsil etmede merkezi bir rol üstlendi.
Fonksiyonlar kavramı bu dönemde kesinleşti.
İlişkiyi Modellemek: Bağımsız bir değişkenin ( x ) en ufak değişimine, bağımlı bir değişkenin ( y ) nasıl tepki verdiğini incelemek mümkün hale geldi. Değişken, artık bir sistemdeki sürekli akışı ve nedensellik ilişkisini gösteriyordu.
Doğanın DiliBu ilerleme, matematiği durağan gerçekliklerden koparıp, doğanın sürekli değişim felsefesiyle ilişkilendirdi.
Kalkülüs sayesinde matematik, bilim insanlarına evrendeki hareket yasalarını ve doğa olaylarını dinamik denklemlerle modelleme gücü verdi.
Değişken, modern mühendisliğin temel taşı olan evrensel değişim diline dönüştü.
Modern Matematik ve Bilgisayar Bilimleri: Soyutlama ve Dijital Uygulama Küme Teorisinden Bellek Adreslerine
19. ve 20. yüzyıllarda değişken kavramı, klasik matematiksel sınırlarını aşarak çok daha soyut ve evrensel bir araç haline geldi.
Soyutlama ve Mantıksal Yapılar: Bu dönemde matematik; Küme Teorisi ve Sembolik Mantık gibi yapılara odaklandı.
Değişkenler, artık sadece sayısal değerleri ( x=5 ) değil, mantıksal önermeleri ( p \Rightarrow q ) veya bir kümenin rastgele bir elemanını
( x \in S ) temsil eden genel yer tutucular oldu.
Küme Tanım Örneği: $$A = \{ x \mid x \text{ bir asal sayıdır} \}$$
Burada x, belirli bir sayıyı değil, asal olma koşulunu sağlayan sonsuz sayıdaki potansiyel adayı temsil eder.
Değişkenin temel felsefesi olan genelleme yeteneği, burada merkezi bir rol oynar.
Fiziksel Konum Temsili (RAM)20. yüzyılın ortalarında bilgisayarların ortaya çıkmasıyla, değişken kavramı tamamen yeni, pratik ve fiziksel bir boyut kazandı.
Programlamada değişken, matematiksel "bilinmeyeni" temsil etme işlevini korurken, buna ek olarak bellek yönetiminin temel bir soyutlama aracı haline geldi.
Bellekteki Konum Temsili: Değişken, artık kağıt üzerindeki bir sembol değildir; bilgisayarın fiziksel belleğinde ( RAM ) bir değerin saklandığı belirli bir adresi temsil eder.
Hexadecimal Kodlardan İsimlendirmeyeVeri Yönetimi: Değişkenler, bu bellek konumunda depolanan veriyi ( 10 veya "Merhaba" ) isimlendirir.
Bilgisayarın dili 0x7ffee4 gibi karmaşık onaltılık ( hexadecimal ) bellek adresleridir.
Geliştiriciler bu adreslerle uğraşmak yerine, insan diline yakın olan değişken isimlerini kullanarak veriyi manipüle eder.
Bu sayede değişken, dijital sistemlerin vazgeçilmez temel işlevi olmuştur.
JavaScript gibi dinamik dillerde bu kavram, dilin esnek yapısı içinde hem basit hem de güçlü bir rol oynar.
Programlamada Değişkenin Evrimi ve Felsefesi Bellek Kutularından Soyut İfadelere
Değişkenler, matematiksel kökenlerinden türemiş olsa da, dijital işlem mantığının gerektirdiği ek katmanlar ve felsefi boyutlar içerecek şekilde evrimleşmiştir.
Matematikteki bir değişken sonsuz bir sayı kümesini temsil ederken, bilgisayar bilimlerindeki değişken; veri tipi, bellek boyutu,
yaşam döngüsü ve kapsam gibi fiziksel sınırlamalarla tanımlanan "yaşayan" bir varlıktır.
Donanım Karmaşıklığından KurtuluşBu evrim, programcıları donanımın fiziksel karmaşıklığından kurtarmayı hedefleyen bir soyutlama hareketidir.
Makine Kodu düzeyinde bir değişken, doğrudan bir bellek adresine ( 0x4F3A gibi) işaret eden bir sayıydı.
Ancak modern dillerle birlikte değişkenler, bu fiziksel adresleri gizleyen semantik etiketlere dönüştü.
Artık geliştirici, 0x4F3A adresindeki bitleri manipüle etmeyi düşünmez; kullaniciAdi = "Ali" diyerek, insan diline yakın bir mantıkla problem çözer.
Mekanikten MimarileşmeyeBu dönüşüm, programlamayı bir "makine operatörlüğü" olmaktan çıkarıp, doğrudan problem çözme sanatına odaklanılan bir mimari sürece dönüştürmüştür.
Değişkenler sayesinde bizler, bilgisayarın nasıl çalıştığına değil, çözmek istediğimiz problemin ne olduğuna odaklanabiliriz.
Değişken, dijital dünyada gerçekliği modellememizi sağlayan en güçlü düşünce aracıdır.
İlk Bilgisayarlar ve Donanım Odaklılık Fiziksel Adresleme ve Manuel Yönetim
Bilgisayarların ilk dönemlerinde ( Makine Dili ve Assembly ), değişken kavramı bugünkü gibi semantik bir etiket değil; doğrudan fiziksel donanımla ilişkilendirilmiş bir gerçeklikti.
Bu çağda programlama, donanımın üzerinde çalışan bir yazılım katmanı değil, donanımın kendisini doğrudan manipüle etme sanatıydı.
Adresler ve Kayıtlar (Registers)Programcılar, verileri saklamak için sayi veya isim gibi kelimeler kullanamazlardı. Bunun yerine, RAM üzerindeki kesin konumu belirten
bellek adreslerini belirtmek zorundaydılar.
Ayrıca CPU'nun içindeki çok hızlı bellek birimleri olan Kayıt Defterlerini (Registers) manuel olarak yönetmek zorundaydılar. Bir veriyi "çağırmak", işlemciye "Git ve 3456 numaralı kutunun içindekini getir" demekti.
Fiziksel Kutu MetaforuBu dönemde değişken, metaforik değil, literal anlamda bilgisayarın fiziksel belleğindeki belirli bir adrese sahip, içi doldurulup boşaltılabilen bir kutu olarak algılanıyordu.
Avantaj ve Bedel: Bu yöntem, aracı katmanlar olmadığı için son derece hızlıydı.
Ancak, yanlış adrese yazmak tüm sistemi çökertebildiği için insan hatalarına son derece açıktı.
0x4F adresinin ne anlama geldiğini koda bakarak anlamak imkansızdı; bu da programların okunabilirliğini ve sürdürülebilirliğini engelliyordu.
Yüksek Seviyeli Dillerin Yükselişi ve Soyutlama Fortran, Lisp ve Sembolik Devrim
1950'lerin sonlarına doğru Fortran ve Lisp gibi ilk yüksek seviyeli dillerin ortaya çıkmasıyla, değişken kavramı tarihindeki ilk büyük soyutlama adımını attı.
Bu diller, değişkenleri donanımın katı sınırlarından kurtararak onları matematiksel formüllere ve insan mantığına çok daha yakın bir yapıya kavuşturdu.
Adreslerden KelimelereBu devrimin en belirgin özelliği Sembolik Adlandırma yeteneğiydi.
Programcılar; karmaşık heksadesimal bellek adresleri yerine, anlamlı sembolik adlar kullanarak verilere erişme imkanı buldular.
Derleyici, arka planda bu isimleri otomatik olarak fiziksel bellek adresleriyle eşleştirerek, geliştiricinin bu ağır yükü taşımasını engelledi.
"Nasıl"dan "Ne"ye GeçişBu teknolojik değişim, programcıların zihniyetinde köklü bir Felsefi Odak Kayması yarattı.
Programcılar artık verinin bellekte "nasıl" saklandığı yerine; veriyi "ne" amaçla kullandığına ve algoritmanın mantığına odaklanabildiler.
Bu soyutlama, kodun insan zihni için yönetilebilir ve farklı donanımlar arasında taşınabilir olmasını sağladı.
Kod artık makineye verilen bir emir listesi değil, bir problemin çözümünün mantıksal ifadesiydi.
Veri Tipleri ve Tip Güvenliği Felsefesi Algol, Pascal ve Statik Disiplin
Değişkenlerin sadece birer etiket olmaktan çıkıp, belirli bir kimliğe büründüğü dönem, Algol ve Pascal gibi dillerin yükselişiyle başlamıştır.
Bu dillerin getirdiği zorunlu statik veri tipleri ( integer, float, string ) ataması, programlama felsefesinde "Doğruluk" ve "Güvenilirlik" ilkelerini pekiştiren bir devrimdi.
Artık bir kutunun üzerine sadece ismini değil, içine ne konulabileceğini de yazmak zorunluydu.
Derleme Zamanı KorumasıTip Güvenliği, yazılım geliştirme sürecine entegre edilen bir sigorta mekanizmasıdır.
Bir değişkene atanacak verinin tipini önceden belirlemek, olası hataları program çalışmadan önce yakalama olanağı sundu. Eğer bir geliştirici, "Sayı" olarak tanımladığı bir değişkene "Metin" atamaya çalışırsa, derleyici bunu reddeder ve programın çökmesini daha kod yazılırken engellerdi.
Optimize Edilmiş Kaynak YönetimiBu kısıtlama, aynı zamanda mühendislik açısından belleğin çok daha verimli kullanılmasını sağladı.
Bilgisayar, değişkenin tipini önceden bildiği için ( 1 integer için 4 bayt, 1 char için 1 bayt ), bellekte o değişken için ne kadar alan ayırması gerektiğini milimetrik olarak hesaplayabiliyordu.
Bu, kaynakların kısıtlı olduğu dönemlerde performansı maksimize eden kritik bir faktördü.
Dinamik Diller ve Esneklik Arayışı (JavaScript) Smalltalk Mirası, Çalışma Zamanı ve Hız
Smalltalk ile başlayan ve internet çağında JavaScript ile zirveye ulaşan dinamik diller akımı, önceki dönemin katı tip tanımlaması zorunluluğunu kaldırarak programlamaya benzersiz bir esneklik ve hızlı prototipleme yeteneği kazandırdı.
Bu yaklaşım, yazılımcının "tip tanımlamakla" vakit kaybetmek yerine, doğrudan iş mantığını kurgulamasına olanak tanıyan pragmatik bir devrimdi.
Değişken Değil, Değer TiplidirDinamik dillerdeki en büyük teknik fark şudur: Tip, değişkenin kendisine değil, değişkenin tuttuğu değere aittir.
Mekanizma: Bu dillerde bir değişkenin tipi, kod yazılırken değil, kod satır satır çalıştırılırken belirlenir.
Motor, atanan değere bakar ve "Şu an bu değişken bir sayıyı tutuyor" der.
Bir sonraki satırda aynı değişkene bir metin atanırsa, motor bunu kabul eder ve "Artık bu değişken bir metin tutuyor" şeklinde durumunu günceller.
Güvenlik vs. EsneklikBu yaklaşım, programlama felsefesinde asla bitmeyen bir tartışmayı; "Esneklik ve Hız" ile "Güvenlik ve Öngörülebilirlik" arasındaki denge arayışını yansıtır.
Dinamik yapı geliştirme hızını muazzam derecede artırır, ancak güvenlik ağların ortadan kaldırır.
Bu nedenle dinamik diller, geliştiriciden derleyici yerine geçerek daha dikkatli, disiplinli ve kapsamlı bir hata yönetimi stratejisi uygulamasını talep eder.
Fonksiyonel Programlama ve Değişmezlik Felsefesi (Immutability) Durum Karmaşasına Karşı Saf Matematiksel Yaklaşım
Fonksiyonel Programlama paradigmasının yükselişiyle, programlamanın temel taşı olan "değişken" kavramının kendisi felsefi olarak sorgulanmaya başlanmıştır.
Geleneksel programlamada değişken, içi sürekli değişen bir kutudur.
Ancak FP yaklaşımı, değişkeni matematiksel bir tanım olarak görür.
Matematikte x = 5 dendiğinde, bu bir "atama" değil, evrensel bir gerçektir; x sonsuza kadar 5'tir.
FP, bu matematiksel kesinliği yazılıma taşımayı hedefler.
Kopyalama Üzerine Kurulu MimariFP, değişkenlerin değerlerinin değiştirilemez olmasını teşvik eder, hatta zorunlu kılar.
Mekanizma: Bir değişkenin değeri atandıktan sonra asla modifiye edilmez ( mutasyona uğramaz ).
Eğer veride bir değişiklik yapılması gerekiyorsa ( bir dizinin sonuna eleman eklemek gibi ), mevcut diziye dokunulmaz; bunun yerine, eski dizinin kopyasını ve yeni elemanı içeren tamamen yeni bir değişken oluşturulur.
Saf Fonksiyonlar (Pure Functions)Bu yaklaşım, programların en büyük düşmanı olan Yan Etkileri en aza indirmeyi hedefler.
Bir değişkenin değeri beklenmedik bir şekilde değişmediğinde, o değişkeni kullanan fonksiyonlar her zaman aynı girdiye karşılık aynı çıktıyı üretir.
Bu, durum karmaşasını ortadan kaldırarak kodun son derece öngörülebilir ve hatasız olmasını sağlar.
Thread Safety (İş Parçacığı Güvenliği)Değişmezlik felsefesi, modern işlemcilerin çok çekirdekli yapısı için kritik bir avantaj sunar.
Paralel İşlemler ( Multi-threading ): Geleneksel yöntemlerde, birden fazla iş parçacığı aynı anda aynı değişkeni değiştirmeye çalışırsa veri bozulabilir.
Ancak değişkenler değiştirilemez olduğunda, okuma işlemi güvenlidir.
Hiçbir iş parçacığı diğerinin verisini bozamaz.
Bu da FP'yi, yüksek performanslı ve dağıtık sistemler için ideal kılar.
Lambda Kalkülüs ve Değişken Bağlama (Akademik Temel) Alonzo Church ve Programlamanın Matematiksel DNA'sı
Programlama dillerindeki değişken kavramının en derin teorik temeli, Alan Turing'in çağdaşı olan Alonzo Church tarafından 1930'larda geliştirilen Lambda Kalkülüsü'ne dayanır.
Bilgisayarlar henüz fiziksel olarak inşa edilmeden önce, Church "hesaplanabilirlik" kavramını matematiksel fonksiyonlar ve değişkenler üzerinden modellemiştir.
Bu modelde değişkenler, fiziksel bellek kutuları değil, yer değiştirme kurallarına tabi olan sembollerdir.
Serbest vs. Bağlı DeğişkenlerLambda Kalkülüs, modern programlamadaki değişken bağlama ve kapsam kavramlarını matematiksel olarak formüle etmiştir.
Lambda İfadesi Örneği: lambda x. x + 1 ( modern JavaScript'teki x => x + 1 ile aynıdır), x değişkeni bir "parametre" olarak tanımlanır ve gövde içerisindeki kullanıma bağlanır.
Bu, değişkenin rastgele bir sembol olmaktan çıkıp, o fonksiyonun bağlamına (context) hapsolması demektir.
Bu teori, bir değişkenin "serbest" ( global veya dış kapsamda ) mi yoksa "bağlı" ( yerel parametre ) mı olduğunun kurallarını kesinleştirmiştir.
Lisp'ten JavaScript'eLisp gibi erken dönem fonksiyonel diller, doğrudan bu teorik temeller üzerine inşa edilmiştir, ancak etkisi bununla sınırlı değildir.
Günümüzde kullandığımız blok kapsamı, kapanışlar ( closures ) ve anonim fonksiyonlar; temelde Lambda Kalkülüs'teki indirgeme kurallarının modern işlemciler üzerindeki birer simülasyonudur.
Değişkenler, bu matematiksel miras sayesinde kodun yapı taşları arasındaki veri akışını yöneten güvenli kanallar haline gelmiştir.
Değişken ve Kimlik: Değer vs. Referans Semantiği (Felsefi İkilem) Varlığın Doğası: Nominal Temsil ve Dolaylı İşaretçiler
Programlamada değişkenler, sadece teknik bir depolama aracı değil, depoladıkları verinin doğasına göre farklı felsefi anlamlar taşıyan varlıklardır.
Bir değişkenin bir veriyi tutması ne anlama gelir? Verinin kendisi mi değişkenin içindedir,
yoksa değişken sadece verinin nerede olduğuna dair bir harita mı tutar?Bu sorular, Değer Tipi ve Referans Tipi ayrımının temelini oluşturur.
Doğrudan (Nominal) Temsilİlkel türlerde, değişken doğrudan değerin kendisini saklar.
Felsefi Bakış: Bu, doğrudan bir temsildir.
Değişken ile değer birdir ve bütünleşiktir.
Değişkenin kutusunu açtığınızda, verinin kendisini bulursunuz. Bu tür değişkenler birbirine atandığında, değer kopyalanır; yani varlık çoğaltılır.
Her değişken kendi bağımsız gerçekliğine sahip olur.
Dolaylı (İşaret Edici) TemsilNesneler ve diziler gibi karmaşık türlerde ise değişken, verinin kendisini değil, bellekteki o nesnenin adresini saklar.
Felsefi Bakış: Bu, dolaylı (işaret edici) bir temsildir.
Değişken, nesnenin kendisi değil, ona ulaşan bir yoldur ( işaret parmağıdır ).
Değişkenin kutusunu açtığınızda veriyi değil, veriye giden bir "yol haritasını" bulursunuz.
Theseus'un Gemisi ParadoksuModern JavaScript'te, const ile bir nesne tanımlandığında ortaya çıkan durum, felsefedeki Theseus'un Gemisi paradoksunu andırır.
Kimlik vs. Durum: const, nesnenin kimliğini sabitler ve değiştirilemez kılar, ancak nesnenin özellikleri değiştirilebilir.
Bu durum, bir nesnenin kimliği ("Ben kimim?") sabitken, durumunun ("Şu an nasılım?") sürekli değişebileceği felsefi bir ikilemi yansıtır.
Yazılım mimarisinde bu ayrımı yönetmek, "State Management" (Durum Yönetimi) konusunun kalbidir.
Modern JavaScript ve Yönetim Felsefesi ES6 Devrimi: Disiplin, Güven ve Mimari Olgunluk
ES6 ile gelen değişim, sadece yeni anahtar kelimelerin dile eklenmesinden ibaret değildir.
Bu, JavaScript'in basit bir betik dili olmaktan çıkıp, büyük ölçekli kurumsal uygulamaların geliştirilebildiği ciddi bir mühendislik diline dönüşümünün ilanıdır.
Bu yeni yönetim felsefesi, geliştiriciye "istediğini yapabilirsin" diyen eski esnek yaklaşımdan, "bunu yapmalısın çünkü bu daha güvenli" diyen yapılandırılmış ve disiplinli bir yaklaşıma geçişi temsil eder.
Mimari İzolasyon ve KapsüllemeEski nesil var kullanımının yarattığı karmaşık fonksiyon kapsamı ve sızıntı sorunları, modern felsefede kabul edilemez riskler olarak görülmüştür.
Blok Kapsamı: Bunun yerine getirilen blok kapsamı mimarisi, değişkenlerin yaşam döngüsünü milimetrik olarak kontrol etmeyi sağlar.
Bu, kodun her bir parçasının diğerinden izole edilmesini ve bir hatanın sisteme yayılmadan kaynağında hapsedilmesini kolaylaştırır.
Güvenilirlik Sözleşmesiconst kullanımıyla değişmezlik kavramı, sadece bir tercih olmaktan çıkıp dil seviyesinde teşvik edilen bir standart haline gelmiştir.
Modern JavaScript felsefesi şunu savunur: "Durum (State) değişimi, yazılımdaki hataların bir numaralı kaynağıdır."
Bu nedenle, değişkenleri varsayılan olarak sabit tutmak, kodun zaman içindeki davranışını tahmin edilebilir kılar.
Bu yaklaşım, dilin "güvenilirlik" ve "modülerlik" ilkelerini pekiştiren, aynı zamanda React, Vue gibi modern kütüphanelerin çalışma mantığıyla tam uyum sağlayan en stratejik adımdır.
İçerik Tamamlandı
Bu konunun temel içeriği burada sona eriyor
Tebrikler! 🎉
Bu konuyu başarıyla tamamladınız! Sabırla ve azimle öğrendiğiniz her şey, programlama yolculuğunuzda önemli bir adımdır. Öğrendiklerinizi pekiştirmek için kod örneklerini tekrar gözden geçirebilir ve kendi projelerinizde uygulayabilirsiniz.
Öğrenme İpuçları
- Kod örneklerini kopyalayıp kendi editörünüzde deneyin
- Her örneği çalıştırın ve sonucu gözlemleyin
- Örnekleri değiştirip kendi versiyonlarınızı oluşturun
- Öğrendiklerinizi not alın ve tekrar edin
- Pratik yapmak için kendi mini projelerinizi oluşturun
Kod Örnekleri İstatistikleri
Bu sayfadaki tüm kod örneklerinin seviye dağılımı
HTML Seviye Dağılımı
CSS Seviye Dağılımı
JavaScript Seviye Dağılımı
Kod Dosyaları
Bu sayfadaki tüm kod dosyalarını dil ve seviyeye göre filtreleyin
var degisken = "deger";
Function scope, hoisting var
let degisken = "deger";
Block scope, yeniden atanabilir
const degisken = "deger";
Block scope, yeniden atanamaz
function test() {
var x = 10;
}
var ile function scope
{
let x = 10;
}
let/const ile block scope
var global = "deger";
En üst seviye tanımlama
console.log(x); // undefined
var x = 5;
var yukarı taşınır, undefined
console.log(x); // ReferenceError
let x = 5;
Temporal Dead Zone hatası
let x = 5;
x = 10; // OK
var ve let yeniden atanabilir
const x = 5;
x = 10; // TypeError
const yeniden atanamaz
Öğrenme Yolu
JavaScript öğrenme yolculuğunuzda neredesiniz?
Bu bölüm, JavaScript öğrenme yolculuğunuzdaki ilerlemenizi görselleştirir. Aşağıda göreceğiniz adımlar, konular arasındaki mantıksal sıralamayı ve öğrenme akışını temsil eder. Tamamlanan konular mavi tonlarda gösterilir ve üzerinde bir onay işareti bulunur. Aktif konu, şu anda üzerinde çalıştığınız bölümdür ve parlak mavi renkle vurgulanır. Sonraki adımlar ise henüz tamamlanmamış konuları gösterir ve daha soluk tonlarda görüntülenir.
Her adım arasındaki oklar, öğrenme sırasını ve konular arasındaki bağlantıyı gösterir. Bu yapı, hangi konuları tamamladığınızı, hangi konuda olduğunuzu ve sıradaki adımlarınızı net bir şekilde görmenizi sağlar.
Değişkenler
var, let, const ve scope kavramları