- Konu sahibi
- #1
JavaScript hoisting nedir?
JavaScript hoisting, değişken ve fonksiyon bildirimlerinin kod çalıştırılmadan önce ilgili kapsamda işleme alınması davranışıdır. Ancak bütün bildirimler aynı şekilde kullanılabilir hâle gelmez:
var bildirimi başlangıçta undefined değerini alır, let ve const bildirimleri ise tanımlandıkları satıra gelene kadar Temporal Dead Zone adı verilen erişilemez durumda kalır. Bu nedenle “bildirimler yukarı taşınır” ifadesi yalnızca basitleştirilmiş bir modeldir.Hoisting nasıl çalışır?
JavaScript bir kapsamı çalıştırırken önce bildirimler için bağlamlar oluşturur, ardından ifadeleri yukarıdan aşağıya yürütür. Hoisting, atama işlemini yukarı taşımaz. Örneğin
var sayi = 10 ifadesinde bildirim hazırlanır; 10 değeri ise yürütme o satıra geldiğinde atanır.
Kod:
console.log(sayi); // undefined
var sayi = 10;
console.log(sayi); // 10
İlk çıktı hata değildir; değişken vardır fakat henüz değer atanmamıştır. Bu davranış, yanlışlıkla eksik veriyle işlem yapılmasına neden olabileceği için
var yerine çoğu durumda let veya const tercih edilir.let ve const neden hata verir?
let ve const bildirimleri kapsam içinde tanınır, fakat tanımlama satırına kadar okunamaz. Bu aralık Temporal Dead Zone’dur.
Kod:
console.log(ad); // ReferenceError
let ad = "Ada";
Buradaki
ReferenceError, değişkenin hiç bilinmemesinden değil, erken erişimin yasak olmasından kaynaklanır. const için de aynı kural geçerlidir. Ayrıca const bildirimi değer ataması olmadan kullanılamaz:
Kod:
const limit = 5; // geçerli
// const digerLimit; // SyntaxError
En güvenli uygulama, değişkeni kullanılacağı yerden önce tanımlamak ve mümkünse başlangıç değerini aynı satırda vermektir.
Bildirim türlerinin farkı
Aşağıdaki karşılaştırma, kodun hangi noktada güvenle çalışacağını seçmeyi kolaylaştırır.
| Bildirim | Erken okuma | Başlangıç durumu | Önemli sonuç |
|---|---|---|---|
| var | Çalışır | undefined | Atama sonraki satırda yapılır |
| let | ReferenceError | TDZ | Tanımlama satırından sonra kullanılmalıdır |
| const | ReferenceError | TDZ | Tanımlanırken değer verilmelidir |
| function bildirimi | Çalışır | Fonksiyon hazırdır | Bildirimin öncesinden çağrılabilir |
Bu tablo,
let ve const için “değişken hiç yoktur” anlamına gelmez. Asıl sınırlama, erken erişimin engellenmesidir. Blok kapsamı da bu kuralları korur; bir if veya for bloğundaki let dışarıdan okunamaz.Fonksiyonlarda hoisting
Fonksiyon bildirimi, gövdesiyle birlikte hazırlandığı için bildirimden önce çağrılabilir:
Kod:
const sonuc = topla(2, 3);
console.log(sonuc); // 5
function topla(a, b) {
return a + b;
}
Buna karşılık fonksiyon ifadesi bir değişkene atanır ve değişkenin hoisting kuralına uyar:
Kod:
calistir(); // TypeError: calistir is not a function
var calistir = function () {
console.log("çalıştı");
};
Burada
calistir başlangıçta undefined olduğu için çağrı sırasında fonksiyon değildir. Aynı örnek let veya const ile yazılırsa erken çağrı ReferenceError üretir. Fonksiyon ifadelerini, atandıkları satırdan sonra çağırmak anlaşılması daha kolaydır.Pratik kullanım kararı
Kod yazarken şu sırayı uygulayın:
- Değişkeni kullanıldığı noktadan önce
constile tanımlayın. - Değer daha sonra değişecekse
letkullanın ve ilk değeri açıkça verin. - Eski kodda
vargörürseniz, erken erişiminundefinedüretebileceğini kontrol edin. - Fonksiyon bildirimi ile fonksiyon ifadesini karıştırmayın; ifade, atama yapılmadan çağrılamaz.
- Aynı isimli bildirimleri ve gereksiz erken erişimleri kaldırarak kodun okunma sırasını yürütme sırasıyla uyumlu hâle getirin.
Hoisting, JavaScript’in kapsam hazırlama davranışını açıklayan bir kavramdır; kaynak kodunda fiziksel satır taşıma işlemi değildir. Beklenmeyen sonucu çözmek için önce bildirimin türünü, ardından erişim satırını ve ilgili kapsamı kontrol edin.
Sık sorulan sorular
Hoisting yalnızca değişkenlerde mi görülür?
Hayır. Fonksiyon bildirimleri de hoisting davranışından yararlanır. Sınıf bildirimleri ise erken erişimde
ReferenceError verdiği için let ve const ile benzer şekilde ele alınmalıdır.typeof kullanarak TDZ hatasını önleyebilir miyim?
Hayır. Hiç bildirilmemiş bir isim için typeof sonucu undefined olabilir; fakat aynı kapsamda henüz başlatılmamış let/const bağı için typeof da ReferenceError verir. Önce ilgili bildirim ve erişim sırasını inceleyin.