JavaScript’te “Hoisting” Kavramı Nedir?

JavaScript’te hoisting kavramı, en kaba tabirle değişken ve fonksiyon tanımlarının kodun üst kısmına taşınması anlamına gelmektedir. Böylece ilgili değişken veya fonksiyon, kodun üst kısmında tanımlanmadığı halde, kodun herhangi bir yerinde kullanılabilirliğine olanak sağlanmış olur.

JavaScript’te “Hoisting” Kavramı

JavaScript’te “hoisting” adını verdiğimiz özellik sayesinde değişkenler ve fonksiyonlar sanki kodun başında tanımlanmış gibi davranır. Yani bir değişkeni ya da fonksiyonu tanımlamadan önce kullanmaya çalışsanız bile, JavaScript sanki onları en başta tanımlamışsınız gibi kabul eder. Haliyle, kodun bazı kısımlarının nerede yazıldığına bakmaksızın çalışması mümkün hale gelir.

“Hoisting” konseptinin bu nevi şahsına münhasır özelliği nedeniyle, kodun daha okunabilir ve organize yazılması teşvik edilir. Zira, bu özelliğin farkında olmadan kod yazmak bazen beklenmeyen sonuçlara yol açabilir. Özellikle “var”, “let” ve “const” kullanımındaki farklılıklar göz önüne alındığında, “hoisting” özelliğinin nasıl çalıştığını anlamak, hataları önlemek ve kodunuzu daha etkili bir şekilde optimize etmek için kritik bir öneme sahiptir.

  • İlk olarak fonksiyonlardaki hoisting işlemini ele alalım. JavaScript’te fonksiyonların türü ne olursa olsun fonksiyon çağrıları “fully hoisted” olarak ayarlıdır. Bu sayede kodun neresinde olursa olsun fonksiyon çağrıldığı anda çalışabilir hale gelir. Örneğin:

Yukarıdaki örneği incelediğimizde, foo() fonksiyonu, önce çağrılmış daha sonra tanımlanmıştır. Ancak “hoisting” sayesinde, fonksiyonun tanımı kodun üst kısmına taşındığı için, herhangi bir kod hatası olmadan çalışmış ve “Merhaba Dünya!” çıktısını vermiştir.

Ancak belirtmek isterim ki, “function expression”, yani fonksiyonu bir değişkene atama işlemi “fully hoisted” değildir. Zira “function expression” hoisted olurken sadece değişkenin tanımı yukarı taşınır, fonksiyonun kendisi değil. Eğer bu değişkeni fonksiyonun tanımlandığı satırdan önce çağırırsanız, bu değişkenin değeri “undefined” olacaktır. Aşağıdaki örneği inceleyiniz:

İlk console.log‘da, myFunction adlı değişken tanımlı ancak ona bir değer atanmamış olduğu için “undefined” olarak loglanır. İkinci console.log‘da ise değişkene fonksiyon atanmış ve fonksiyon çağrıldığı için “Merhaba!” mesajı loglanır.

Sıra geldi, değişken atamak için kullandığımız anahtar kelime olan var, let ve const anahtar kelimeleriyle “hoisting” nasıl oluyormuş onu göstermeye. JavaScript’te “var”, “let” ve “const” anahtar kelimeleri, “hoisting” kavramına farklı şekillerde tepki verirler.

İlk olarak şunu belirtmek istiyorum; “hoisting” ile değişkenlerin kendileri yukarı taşınsa da sahip oldukları değerler taşınmaz.

  • JavaScript’te var anahtar kelimesiyle tanımlanan değişkenler, başlangıçta otomatik olarak undefined değerine sahiptir. Tahmin edebileceğiniz üzere bu durum, değişken için bellekte yer ayrıldığını, ancak henüz bir değer atanmadığını anlatır. Eğer bu değişkene değer atanmamışsa, değer atanana kadar undefined olarak kalacaktır. Örneğin:

Yukarıdaki kodumuzda, ornekDegisken adlı değişkeni tanımladık ama başlangıçta bir değer atamadık, bu yüzden ilk loglama işleminde undefined çıktısını aldık. Daha sonra bir değer atadık ve hemen ardına yazdığımız ikinci loglama işleminde çıktıyı aldık.

let ve const anahtar kelimeleri, ES6 ile birlikte JavaScript’e eklenmiş olan yeni değişken tanımlama yöntemleridir. Her birinin kendine has kullanım alanı olsa da biz bu yazımızda var ile aralarındaki “hoisting” davranış farkını inceleyeceğiz.

  • let ile tanımlanan değişkenler de tıpkı var anahtar kelimesinde olduğu gibi “hoisting” mekanizması tarafından kodun başına taşınırlar. Ancak farklı olarak, bu değişkenlere otomatik olarak undefined değeri atanmaz. Bu nedenle, bir değişkeni let ile tanımladıktan önce erişmeye çalışırsanız, bir ReferenceError hatası ile karşılaşırsınız. Örneğin:

Yukarıdaki kodda, başlangıçta ornekDegisken‘in değerini ekrana yazdırmaya çalışıyoruz. Fakat bu noktada değişken henüz tanımlanmadığı için “Cannot access ‘ornekDegisken’ before initialization” şeklinde bir hata mesajı alıyoruz. Bu hatayı düzeltmek için ilgili satırı kaldırdığımızda, kodun devamında ornekDegisken‘i let anahtar kelimesiyle tanımlıyoruz ama herhangi bir değer atamadık. Böyle durumlarda, ilgili değişkenin başlangıç değeri otomatik olarak undefined olarak belirlenir. Kodun devamında ornekDegisken‘e “Merhaba!” değerini atadığımızda ise değişkenin değerini ekrana yazdırdığımızda “Merhaba!” çıktısını vermektedir.

  • const da benzer şekilde hoisting edilir. Ancak yine let gibi, tanımlanan değişkene otomatik olarak bir başlangıç değeri atanmaz. Ek olarak, const ile bir değişken tanımlarken bu değişkene başlangıçta bir değer atamak zorunludur. Çünkü const, sadece bir kere atanabilen ve sonrasında değiştirilemeyen bir değişkeni ifade eder.

Yukarıdaki kodda, ilk olarak ornekSabiti adında bir sabiti tanımlamadan kullanmaya çalışıyoruz ve hata alıyoruz. Ardından bu sabiti tanımlamaya çalışıyoruz fakat const ile tanımlanan bir değişkene başlangıçta değer atanmadığı için hata alıyoruz. Sonrasında ise örnekSabiti değişkenini tanımlarken değer atamasını yapıyoruz. Haliyle değerimiz ekrana yazdırılıyor.

Özetle, eğer bir değişken, var anahtar kelimesiyle tanımlanmışsa ve bu değişken “hoisted” oluyorsa, o değişkenin başlangıç değeri undefined olarak atanır. Ancak let ve const ile tanımlanan değişkenler “hoisted” olduğunda bile erişilemez durumda kalır ve erişilmeye çalışıldığında hata alınır.

❗ Hoisting ile her ne kadar kodun daha modüler bir hale gelmesi kolaylaşıp kodun çalışma hızı artsa da mümkün olduğunca hoisting’ten kaçınmak gerekir. Özellikle değişken bildirimlerinde var yerine let veya const tercih edilmelidir. Zira kodunuzda bellek sızıntıları (memory leak) ve/veya yakalanması zor hatalar ortaya çıkabilir.

İlgili Makaleler

Bir yanıt yazın

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir

Başa dön tuşu