Javascript – hoisting

article-thumbnail

Jednym z najpowszechniejszych pytań rekrutacyjnych dla programisty Javascript jest wyjaśnienie, czym jest tzw. hoisting. Zagadnienie to jest ciekawie, głównie dlatego, że dotyka samego sposobu działania Javascript’u. Związane z nim są podstawowe różnice, między zmiennymi var i let, ale także między sposobami deklaracji funkcji.

Czym jest hoisting

Hoisting zwany inaczej windowaniem to mechanika „przenoszenia” deklaracji zmiennych na samą górę dokumentu podczas interpretacji. Oznacza to, że wszystkie utworzone zmienne, są teoretycznie dostępne przed ich utworzeniem w kodzie. Brzmi dziwnie i nielogicznie. Zobaczmy o co chodzi.

<script>
  	a = 5;
	document.write(a);
	var a;
</script>

Jak widać, mogliśmy ustawić wartość zmiennej i ją wyświetlić, jeszcze zanim zmienna została zadeklarowana. Jednak jeżeli przypisanie wartości umieści obok deklaracji to uzyskamy wynik undefine.

<script>
	document.write(a);
	var a = 5;
</script>

Na podstawie tego, wiemy, że JS przenosi deklarację zmiennej na górę dokumentu, ale nadanie jej wartości odbywa się w miejscu wskazanym w kodzie.

Windowanie Funkcji

Hoisting dotyczy nie tylko zmiennych ale również funkcji (zazwyczaj). Zobaczmy na przykładzie

<script>
	document.write(suma(1,2));

    function suma(a,b)
    {
        return a+b;
    }
  
</script>

Uzyskaliśmy efekt identyczny jak w przypadku zmiennych. Możemy użyć funkcji przed jej deklaracją. Co się jednak stanie gdy spróbujemy przypisać funkcję do zmiennej?

<script>
    try
    {
      document.write(suma(1,2));
    }
	catch(err)
    {
      document.write(err);
    }

	document.write('</br>');
	// Spradzenie dla funkcji sztrzałkowej
	try
    {
      document.write(roznica(1,2));
    }
	catch(err)
    {
      document.write(err);
    }
	

    var suma =  function (a,b)
    {
        return a+b;
    }

	var roznica = () =>
    {
        return a-b;
    }
  
</script>

Jak widać w takim przypadku, nie przypisano funkcji do zmiennej.

Let i const a var – różnica wynikająca z hoistingu

Zobaczmy, co się stanie, gdy użyjemy słowa kluczowego let, zamiast var. Aby to zobaczyć, zmodyfikuję nieco kod z pierwszego przykładu.

<script>
    try
    {
		a=5
      	document.write(a);
    }
    catch(err)
    {
      	document.write(err);
    }
	let a;
</script>

Uzyskaliśmy błąd. Oznacza on, że zmienna a podlega windowaniu, ale JS blokuje jej użycie przed inicjalizacją.