• dmchoi
  • 자바스크립트 호이스팅(Hoisting)

    2022년 04월 23일

    (제가 이해한 내용을 정리한 것이므로, 틀린 부분이 있을 수 있습니다. 틀린 부분이 있다면 지적해주세요!)


    MDN web docs에 따르면 호이스팅을 아래와 같이 설명하고 있다.

    인터프리터가 변수와 함수의 메모리 공간을 선언 전에 미리 할당하는 것

    그래서 보통 호이스팅이 무엇이냐고 하면, 변수 선언이 스코프의 최상단으로 올려지는 것 처럼 동작하는 것이라고 얘기한다.


    이번 포스팅의 목적은 변수 선언 키워드인 var, let, const에서의 호이스팅 동작 원리에 대해 알아보는 것이다.


    그 전에 먼저 변수 생성 단계에 대해 알아야 하는데, 변수 생성에는 3단계가 있다.

    1. 선언 단계 : 변수를 스코프(실행 컨텍스트)의 변수 객체에 등록하는 단계로 런타임 이전에 실행된다.
    2. 초기화 단계 : 실행 컨텍스트에 등록한 변수를 위한 메모리를 할당하고 undefined로 초기화 하는 단계
    3. 할당 단계 : 값을 할당하는 단계

    변수 생성 단계에 대해 잘 몰랐을 때, let이 선언 단계와 초기화 단계가 따로 진행된다는 말이 도통 무슨 말인지 몰랐다.

    let a;라 하면 코드 그 자체만 보고서는 그냥 선언되자마자 undefined로 초기화 되는거 아닌가? 라고 생각했다.

    선언 단계가 런타임 이전에 실행된다는 것을 알게 되고 나서야 무슨 말인지 이해가 됐다.

    var에서의 호이스팅

    다음 예제를 보자

    console.log(a); // undefined
    
    var a = 1;

    변수 a를 선언하기 전에 에러가 발생하지 않고 참조가 가능하다. 단, undefined를 반환한다.

    var로 선언한 변수는 런타임 이전에 자바스크립트 엔진에 의해 암묵적으로 선언 단계와 초기화 단계가 동시에 진행이 된다.

    선언 단계에서 스코프에 변수 식별자를 등록해 자바스크립트 엔진에게 변수의 존재를 알린다. 그리고 직후에 초기화 단계에서 undefined로 변수를 초기화 한다.

    그래서 위의 예제처럼 변수 선언문 이전에 변수에 접근해도 스코프에 변수가 존재하기 때문에 에러가 발생하지 않는 것이다.

    let과 const에서의 호이스팅

    다음 예제를 보자

    console.log(a); // Uncaught ReferenceError: a is not defined
    
    let a;

    변수 a를 선언 전에 참조하려하면 var에서와는 다르게 참조 에러가 발생한다.


    let으로 선언한 변수는 선언 단계와 초기화 단계가 분리되어 진행된다.

    즉 런타임 이전에 자바스크립트 엔진에 의해 암묵적으로 선언 단계가 먼저 실행되지만 초기화 단계는 변수 선언문에 도달했을 때 실행된다.

    그래서 위의 예제처럼 초기화 단계가 실행되기 전에 변수에 접근하려고 하면 참조 에러가 발생한다.

    그럼 let에서는 호이스팅이 안되는거 아니냐?

    다음 예제를 보자

    let a = 1;
    {
      console.log(a); // Uncaught ReferenceError: Cannot access 'a' before initialization
      let a = 2;
    }

    만약 호이스팅이 일어나지 않는다면 전역에서 선언된 a의 값을 출력해야한다.

    그러나 호이스팅이 일어나기 때문에 참조 에러가 발생하게 된다.

    let에서도 호이스팅이 일어나지만 단지 일어나지 않은 것 처럼 보일뿐이다.


    const로 선언한 변수는 선언, 초기화, 할당이 동시에 이뤄진다.

    그런데 런타임 이전에는 할당이 불가능하기 때문에 실제 코드를 만나고 나서야 변수 선언, 초기화, 할당이 동시에 일어난다.


    참고로 let과 const로 선언한 변수는 스코프 시작 지점부터 초기화 단계 시작 지점 까지 변수를 참조할 수 없는데, 이 구간을 TDZ(Temporal Dead Zone)라고 한다.


    정리하면,

    호이스팅이란 변수를 선언 했을 때 선언부가 마치 스코프 최상단으로 끌어올려지는 것 처럼 동작하는 현상을 의미한다.

    var와 let/const 모두 호이스팅이 일어나긴 하지만, 변수 생성 방식에 따라 조금 다르게 동작한다.

    var는 런타임 이전에 변수 선언과 초기화가 동시에 일어나서 선언 전에도 참조가 가능하지만

    let은 선언과 초기화가 분리돼서 진행되고, const는 런타임 이후에 선언과 초기화, 할당이 동시에 진행되기 때문에 실제 코드에 도달하기 전에 참조를 했을 경우 에러가 발생한다.

    Tags
      © 2021 dmchoi, Powered By Gatsby.