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.