ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 자바스크립트 - 호이스팅(Hoisting)이란?
    JavaScript/기본 2020. 7. 19. 16:54

     

    호이스팅(Hoisting)이란?

    scope(스코프) 안에서의 변수 선언을 최상위에서 선언한 것과 동등하다는 의미를 가진다.

    즉, 변수가 선언되기 이전에 변수를 사용하면, 변수가 사용된 블럭 범위의 맨 위로 변수를 끌어올린다는 말이다.

    var x = '외부 scope';
    function fnc() {
      console.log(x); // undefined
      var x = '내부 scope';
    };
    
    fnc();

    함수 fnc를 실행해보면, 콘솔 창에는 undefined가 출력이 된다.

     

    왜 undefined가 출력이 될까?

    그 이유는 var 키워드로 선언된 변수는 선언 단계와 초기화 단계가 한번에 이루어지는데, scope(스코프) 안에서 선언된 변수는 항상 최상위에 선언한 것과 동등한 의미를 가지기 때문에 즉, 호이스팅(Hoisting)이 발생했기 때문이다.

    호이스팅(Hoisting)이 발생할 때, 자바스크립트에서는 위에서 작성된 코드를 아래와 같이 인식한다.

    var x = '외부 scope';
    function fnc() {
      var x // 호이스팅 발생!
      // 선언과 동시에 undefind로 초기화가 진행
      
      console.log(x); // 그래서 undefined가 출력
      var x = '내부 scope';
    };
    
    fnc();

    저렇게 fnc 함수 scope(스코프) 안에서 변수 x가 최상위에서 선언되는 것으로 인식하는 것을 알 수 있다.

    이렇게 호이스팅(Hoisting)은 JavaScript 인터프리터가 코드를 해석할 때 변수 및 함수의 선언 처리, 실제 코드 실행두 단계로 나눠서 처리하기 때문에 발생하는 현상이다.

    하지만 JavaScript 인터프리터가 내부적으로 코드를 이런 방식으로 처리한다는 것일 뿐, 실제 코드 라인이 변경되거나 하는 건 절대 아니다.

    또, var로 선언된 변수는 호이스팅으로 인해 변수가 선언되기 전에도 변수를 사용할 수도 있다.

    name = 'Lim';
    var name;
    // 위는 아래와 같은 의미를 가진다.
    var name;
    name = 'Lim';

     

    그렇다면 var와 let / const에서의 호이스팅(Hoisting)은 차이가 있을까?

    사람들은 보통 let과 const는 호이스팅(Hoisting)을 수행하지 않는다라고 생각한다.

    하지만, 그것은 잘못된 생각이며 var와 똑같이 호이스팅(Hoisting)이 발생한다.

    많은 사람들이 let과 const 선언에서 호이스팅(Hoisting)이 발생하지 않는다라고 느껴졌던 이유는 바로 let과 const에서 TDZ에 의해 제약을 받는다는 것을 모르고 그냥 오류가 발생했다고 생각했기 때문이다.

     

    여기서 Temporal Dead Zone(TDZ)란?

    선언은 되어있지만 아직 초기화가 되지 않아 변수에 담길 값을 위한 공간이 메모리에 할당되지 않은 상태를 말한다.

    아직 말로 해서는 감이 아직 오지 않는다.

    출처 : https://dmitripavlutin.com/javascript-variables-and-temporal-dead-zone/

    그림을 본 다음 아래 예제를 보면, 아래 예제에서는 변수를 초기화되기 전에 액세스를 하려고 하려고 한다.

    console.log(name); // throws a ReferenceError
    const name = 'Lim';

    하지만 결과는 var처럼 undefined를 반환하지 않고, ReferenceError가 발생한다.

    이것은 바로 TDZ 때문이며, 이는 코드 예측을 가능하게 하고 버그를 쉽게 찾아낼 수 있게 해주는 장점이 있다.

    그래서 우리는 var를 쓰지 않고, const와 let을 써야하는 이유이기도 하다.

    // const name에 값을 할당하기전에 name에 접근하면, TDZ에 의해 ReferenceError가 발생하게 된다.
    console.log(name); // throws a ReferenceError
    const name = 'Lim';
    
    // 반대로 name이 실행된 이후에 접근 가능
    const name = 'Lim';
    console.log(name); // Lim
    

    따라서 위의 예제와 같이 실행되기 전까지 액세스 할 수 없는 현상을 TDZ라고 부른다.

     

    결과적으로 정리하지면,

    var에서는 호이스팅(Hoisting)이 발생하고, let과 const의 변수 선언에서는 호이스팅(Hoisting)이 발생하지 않는 것이 아니다. 즉, 모든 변수 선언에서는 호이스팅(Hoisting)이 발생한다.

    let과 const에서의 호이스팅은 let과 const는 scope(스코프)에 진입할 때 변수만 만들어지면 TDZ가 생성되는 것이기 때문에 변수가 액세스 할 수가 없는 것이다.

    let과 const 변수가 완전히 선언(초기화 또는 값 할당)되면 , TDZ를 떠나게 될 것이고, 떠난 상태가 되면 그때부터 변수를 사용있게 된다.

     

    댓글

Designed by Tistory.