MySQL Java JavaScript PHP Python HTML-CSS C-sharp

Hoisting

Hoisting reprezintă procesul de accesare a variabilelor înainte de a fi definite. Această conceptie poate părea puțin ciudată, dar este legată de modul în care funcționează compilatorul JavaScript. Compilarea codului are loc în două treceri.

În prima trecere, compilatorul obține toate declarațiile de variabile, toți identificatorii. În acest moment, niciun cod nu este executat, metodele nu sunt apelate. În a doua trecere, se realizează efectiv execuția. Chiar dacă variabila este definită după utilizarea sa directă, nu va apărea nicio eroare, deoarece în prima trecere, compilatorul deja știe toate variabilele.

Cu alte cuvinte, este ca și cum codul este "ridicat" cu definițiile variabilelor și funcțiilor înainte de utilizarea lor directă. Termenul "hoisting" este un cuvânt în limba engleză și se referă la acest proces.

Variabilele var

Variabilele var, care cad sub hoisting, primesc implicit valoarea undefined. De exemplu, să luăm următorul cod simplu:

console.log(foo);

Apelarea lui va genera o eroare ReferenceError: foo is not defined.

Adăugăm definiția variabilei:

console.log(foo);   // undefined
var foo = "Tom";

În acest caz, consola va afișa valoarea "undefined". La prima trecere, compilatorul află despre existența variabilei foo. Aceasta primește valoarea undefined. La a doua trecere, este apelată metoda console.log(foo).

Să luăm un alt exemplu:

var c = a * b;
var a = 7;
var b = 3;
console.log(c); // NaN

Aici, avem aceeași situație. Variabilele a și b sunt utilizate înainte de a fi definite. Implicit, li se atribuie valoarea undefined. Dacă se multiplică undefined cu undefined, rezultatul va fi Not a Number (NaN).

Aceeași logică se aplică și în cazul utilizării funcțiilor. Putem apela mai întâi o funcție, iar apoi să o definim:

display();

function display(){
   console.log("Hello Hoisting");
}

În acest caz, funcția display va funcționa fără probleme, în ciuda faptului că este definită după apel.

Cu toate acestea, trebuie să facem distincția între această situație și cazul în care funcția este definită ca o variabilă:

display();

var display = function (){
   console.log("Hello Hoisting");
}

În acest caz, vom obține o eroare TypeError: display is not a function. La prima trecere, compilatorul obține, de asemenea, variabila display și îi atribuie valoarea undefined. La a doua trecere, când trebuie să apelăm funcția căreia această variabilă face referire, compilatorul observă că nu există nimic de apelat încă: variabila display este încă egală cu undefined. Și va fi generată o eroare.

Variabilele let și const

Procesul de hoisting pentru variabilele let și const va fi diferit: spre deosebire de variabilele var, nu li se atribuie o valoare inițială la hoisting. Așadar, am văzut mai devreme că, dacă folosim variabilele var înainte de a le declara, acestea primesc implicit valoarea undefined. Acum să vedem cum se comportă o variabilă let:

console.log(foo);   // Uncaught ReferenceError: Cannot access 'foo' before initialization
let foo = "Tom";
console.log(foo);   // nu se va executa

În acest caz, la prima linie vom obține o eroare:

Uncaught ReferenceError: Cannot access 'foo' before initialization

Trebuie să facem distincția între această situație și momentul când variabila let este declarată, dar nu este inițializată:

let foo;            // implicit, foo = undefined
console.log(foo);   // undefined
foo = "Tom";
console.log(foo);   // Tom

Variabila let neinițializată implicit va avea valoarea undefined, și în acest caz, nu vom obține eroare.

Același principiu se aplică și în cazul constantelor:

console.log(foo);   // Uncaught ReferenceError: Cannot access 'foo' before initialization
const foo = "Tom";
console.log(foo);   // nu va genera eroare
← Lecția anterioară Lecția următoare →