var,let,const arasındakı fərqlər: Scopelar və Hoisting

Ismayil Hasanov
ABB Innovation
Published in
5 min readDec 4, 2023

Biz JavaScript-də var, let və const açar sözləri(keyword) ni istifadə edərək müxtəlif dəyişən(variable)-lar yaradırıq. Və buna hər hansı bir variable-ın declare olunması deyirik. Eyni zamanda bir dəyişənimiz yəni variable-mıza dəyər təyin edə (assign) bilirik. misal:(b=5)

const name = "Ahmet" 
// declare | Assign

let number = 10;
// declare | Assign

var isOkay = false;
// declare | Assign

İndi isə var, let və const arasındakı fərqlərə baxaq

Birinci fərq (Redeclare məsələsi)

JavaScript-in let və const çıxarmasının səbəbi ilk növbədə varın özündə gətirdiyi boşluqlar (issue) lar idi. Bunlardan birincisi var ilə yaratdığımız dəyişənin (variable) eyni adda yenidən yaranması məsələsi idi. Aşağıdakı nümunədə bunu daha yaxşı anlaya bilərik

var name = "Hasan"
var name = "Suleyman" // dəyişən yenidən redeclare olunur və son qiyməti qalır

console.log(name); // Konsolda Suleyman Ifadəsi əks olunur

Yuxarıda olan kodu özünüzdə test edərək nəticəni görə bilərsiniz.
Normalda digər proqramlaşdırma dillərində eyni adda iki variable yaratmaq olmur. Sistem error çıxarır.Var da bunun mümkün olması müxtəlif problemlər və buglara yol açırdı. ES6 da let və const un gəlməsi bu problemin qarşısını aldı. Gəlin aşağıdakı nümunəyə baxaq

Eyni halın let ilə qarşılığı

let name = "Hasan";
let name = "Suleyman"; //ERROR

Eyni kodu JavaScript faylınıza atdığınızda error əldə etdiyinizi görəcəksiniz. Burdan o nəticəyə gəlirik ki biz var keyword-u ilə bir dəyişəni yenidən redeclare etdikdə sistem bunu qəbul edir. Bu da çox zaman kodlarda müəyyən problemlərə gətirib çıxarır. let həmçinin const ilə isə bir dəyişəni redeclare etdikdə biz compile zamanı error alırıq.

Let və Const arasındakı fərq

Let və const isə hər ikisi yenidən re-declare olunmasada birinə yəni let-ə yenidən dəyər təyin edə bilirik (re-assign). Const isə bir dəfə assign olunub sabit qalır və ona başqa dəyər təyin etmək mümkün olmur.

    // let üçün re-assign
let data1 = "Hasan"
data1 = "Ismayil" // dəyər dəyişdi
console.log(data1); // : konsolda Ismayil-ı görürük


// const üçün re-assign
const data2 = "musa" // assign
data2 = "Ismayil" // Error - TypeError: Assignment to constant variable.

İkinci fərq (Scope məsələsi)

C#, Java kimi digər proqramlaşdırma dillərində blok daxilində yazılmış dəyişənlər (variables) blokun içinə aid olur və onlara blokun çölündən əl çatmaq mümkün olmur. JavaScript də isə bu fərqlidir.

JavaScriptdə bizim var ilə declare etdiyimiz variable-lar global və function scope olur. Gəlin aşağıdakı nümunəyə baxaq:


let isOkay = true;
if(isOkay){
var number = 20;
console.log("if scope:",number);
}
console.log("global scope:number",number);
console.log("window:",window.number);

Yuxarıda olan nümunəyə fikir versək bizim hər üç konsolumuz number dəyərini göstərir.Yəni ki number dəyişəni if blokunun içində olmasına baxmayaraq global scope olur və biz ona if-in çölündən əl çata bilirik. Global scope olduğunun bir digər sübutu isə bizim window obyektimizdən number dəyərini götürə bilməyimizdir.

PS:Bizim globalda təyin etdiyimiz dəyərlərimiz JavaScript-in bizə verdiyi window dəyəri ilə əl çatan olur. “window.number”ın bizə əl çatan olması o deməkdir ki bizim number dəyişənimiz global scope-dadır

İndi isə function üçün var nümunəsinə baxaq.

function Test(isOkay){
if(isOkay){
var number = 20;
console.log(number);
}
console.log("function scope:",number);
}

Test(true)

Bu nümunə də isə bizim number dəyişənimiz function scope olur və buna görə if blokunun içində olmasına baxmayaraq onu functionun istədiyimiz yerində çağıra bilirik. Yekun olaraq bu nümunələrdən anlayırıq ki bizim var keywordu ilə yaratdığımız dəyişən, global və ya function scope olur.

Let və const isə “block scope” — a daxildirlər və olduqları block-dan çöldə çağrıla bilmirlər. Eyni nümunələrə let və const ilə nümunəyə baxaq.

function Test(isOkay){
if(isOkay){
let number1 = 20;
const number2 = 21;
console.log("let:",number1); // 20
console.log("const:",number2); // 21
}
console.log("let:",number1); //Reference Error
console.log("const:",number2); // Reference Error
}

Test(true)

Yuxardakı kodu işə saldıqda görə biləcəksiniz ki “if” bloku daxilində yazdığımız kodlar işləyir lakin onun çölündən bizim həmin dəyişənlərə çatmağımız mümkün olmur və biz reference error alırıq.Buna da let və const - un var-dan fərqli olaraq block scope olmağı deyilir.

Üçüncü fərq (Hoisting məsələsi)

Hoisting bizim javascriptdimizdə default olaraq gələn bir xüsusiyyətdir hansı ki bu bizim dəyişənimizi declare etmədən ona çatmaq şansı verir.
var — let — const arasındakı əsas fərqlərdən biridə bu hoisting məsələsində öz əksini tapır.

Əgər biz var ilə bir dəyişəni bir dəyişəni əvvəl istifadə edib ondan sonra declare etsək normalda error almalıyıq.Lakin hoisting məntiqi sayəsində JavaScript gedib bir növü aşağını yoxlayır ki bizim istifadə etdiyimiz dəyişən hardasa declare olunubmu və buna görə bizə error qaytarmır. Biz sadəcə olaraq declare elədiyimizdən qabaqkı hissə də dəyərimiz undefined olaraq qalır. Aşağıdakı nümunəyə baxaq:

console.log(number) // undefined

var number = 50

console.log(number) // 50

Normalda birinci konsol hissəsində error almaq yerinə undefined dəyər alırıq hansı ki bu da bizim number dəyərimizin hoist olmasına görə olur. yəni proqram ,əvvəl, number dəyərinin istifadə olunduğunu görür və gedib aşağı sətrlərdə bu dəyişəsinin declare olub olmadığına baxır. Əgər declare olunubsa bizə error qaytarımır sadəcə declare olunmamışdan əvvəkli dəyər undefined olur

İndi eyni məntiqin let və const da işləməsinə baxaq:

console.log(number)
// ReferenceError: Cannot access 'number' before initialization

let number = 50

Eyni məntiqi let və const ilə yoxladıqda yuxarıda comment-də qeyd etdiyim error-u alacağıq. Bu hissə də ən önəmli məqam odur ki bizim əslində variable-mız hoist olunur. Bir çox insan bunun let və const un hoist olunmamasından qaynaqlandığını düşünür və bunu var ilə fərq olaraq adlandırır. Lakin bizim aldığımız errorun səbəbi Temporal Dead Zone
dediyimiz anlayışdır. Əvvəl temporal dead zone-un nə olduğunu izah etmək istəyirəm.

Temporal Dead Zone (TDZ)

Biz let və const la dəyər tanıdıb həmin tanıtmadan əvvəl dəyər üzrə bir əməliyyat etmək istədiyimiz zaman Temporaldeadzone yaranır. Temporal deadzone bizim kod blokumuzda yaranan xüsusi bir sahədir, hansı ki scopun başlanğıcından başlayıb dəyişənimizin(varible) declare olunduğu yerə qədər gedir.Aşağıdakı Nümunə bunu tam açıqlayacaq.

{ //blokun başlanığıcı
// TDZ Başlayır
// TDZ Davam edir
// TDZ Davam edir
// TDZ Davam edir
console.log(hobby); // TDZ Davam etdiyi üçün Reference Error Alırıq
// TDZ Davam edir
// TDZ Davam edir
let hobby= "Reading Book"; // TDZ Bitir
// Burdan etibarən isə TDZ mövcud deyil
}

Yuxarıda qeyd etdiyim koda baxaraq anlamaq olar ki TDZ scopun başlanğıcından let hobby = “Reading book” hissəsinə qədər yaranır və buna görə bizim “console.log(hobby)” hissəsimiz dead zone da qalaraq reference error verir. Bunun isə hoisting ilə əlaqəsi yoxdur. Əslində buna baxmayaraq bizim datamız arxa planda hoist olunur.

Xülasə:

var → global scope-dur, hoist olunur, re-declare və re-assign olunur
let → Block scope-dur, TDZ-i var, re-declare olunmur, re-assign olunur
const → Block scope-dur. TDZ-i var, re-daclare olunmur, re-assign olunmur.

--

--