Nadpisywanie zmiennych globalnych w javasript

W przypadku nadpisywania zmiennych globalnych, javascript nie zawsze zachowuje się intuicyjnie. Zmienna nie musi być globalna, wystarczy że jest zdeklarowana powyżej funkcji w której jesteśmy.

Zgodnie z intuicją

Powiedzmy, że mamy zmienną x zadeklarowaną globalnie.

 var x = 1;
 
 const log = () => {
   console.log(x)
 }

 log()  // 1
  


Wszystko wygląda zgodnie z oczekiwaniem. Funkcja log wyświetla globalną zmienną x.
Rozbudujmy nieco przkład:

 var x = 1;
 
 const log = () => {
   console.log(x)
   x = 2;
   console.log(x)
 }

 log()  // 1 2
  

Tutaj też wszysko zgodnie z oczekiwaniem. Najpierw dostajemy wartość x = 1, a następnie x = 2.

Nie do końca zgodnie z intuicją

Co jednak jeśli ponownie zadeklarujemy zmienną x?

 var x = 1;
 
 const log = () => {
   console.log(x)
    var x = 2;
   console.log(x)
 }

 log()  // undefined 2
  

Tutaj intuicja może nas już trochę zawieść. x w pierwszym console.log stał się undefined. Co takiego się stało?

Javascript deklaruje zmienne na początku

Kiedy deklarujemy jakąś zmienną w javascript, czy to przy pomocy const, let czy var, kompilator na samym początku deklaruje te zmienne. Jeśli zmienna istnieje w scopie wyżej wtedy zostaje nadpisana. Można powiedzieć że w naszym przypadku javascript wykonał tak naprawdę następujący kod:

 var x = 1;
 
 const log = () => {
   var x;
   console.log(x)
   var x = 2;
   console.log(x)
 }

 log()  // undefined 2
  

Podsumowanie

Myślę że w codziennej pracy raczej nie natrafimy na tego typu przypadek, jednak dobrze jest zdawać sobie sprawę z takiego zachowania. Jeśli zrobimy to samo ale zamiast var użyjemy let, wtedy javascript rzuci wyjątkiem.