JavaScript

Hoisting - JS 엔진이 하는 일

이요시야 2023. 5. 15. 12:10

'Hoisting' 이란 ?

영어 단어 hoist는 끌어올리기 를 뜻한다. 그렇다면, JS에서의 hoisting이란 무엇일까?

 

호이스팅(hoisting)이란, 

js interpreter가 변수와 함수의 메모리 공간을 선언 전에 미리 할당하는 것이다.

 

더 자세하게는, 변수의 선언과 초기화를 분리한 후, 선언만 코드의 최상단으로 옮기는 것이다.

 

호이스팅에 따르면, js에서는 변수의 선언만 최상위의 순서로 끌어올려진다.

따라서, 변수를 정의하는 코드보다 사용하는 코드가 앞서 등장할 수 있다.

다만, 선언과 초기화를 함께 수행하는 경우에는 선언 코드까지 실행해야 변수가 초기화된 상태가 된다.

 

 

호이스팅의 규칙

호이스팅의 존재로 우리가 알아야 할 두 가지가 있다.

 

  1. var로 선언한 변수의 경우, 호이스팅 시 undefined로 변수를 초기화한다.
  2. 반면, let과 const로 선언한 변수의 경우, 호이스팅 시 변수를 초기화하지 않는다.

 

이 규칙을 정리하면 세 가지 경우가 나온다.

 

  1. 선언된 함수는 상단에서 참조, 호출이 가능하다.
  2. 선언된 var는 상단에서 참조, 할당이 가능하다.
  3. 선언된 let, const는 상단에서 참조, 할당이 불가능하다.

 

예제 코드로 호이스팅 규칙을 살펴보자

 

 

예제 코드

함수 선언 전에, 함수를 호출한 경우이다.

catName("나비"); // 선언 보다 앞선 호출

function catName(name) {
  console.log("제 고양이의 이름은 " + name + "입니다");
}

// 결과: "제 고양이의 이름은 나비입니다"

함수 호출이 함수 자체보다 앞에 있지만, 그럼에도 이 코드는 동작한다. 이것이 js에서 실행 컨텍스트가 동작하는 방식이다. 

 

 

변수 생성 과정과 'TDZ'

js의 모든 자료형과 변수 선언에는 호이스팅이 일어난다.

그런데 let, const, class를 이용한 선언문은 호이스팅이 발생하지 않는 것처럼 동작한다. 

var로 선언된 변수와 달리, let, const, class 키워드로 선언된 변수를 선언 이전에 참조하면 참조 에러(ReferenceError)가 발생한다.

 

호이스팅은 분명 모든 변수와 함수에서 필연적으로 일어나는 것인데, 특정 조건에서 선언 전 참조는 오류를 발생시킨다.

이 이유는 변수의 생성 과정을 통해 알 수 있다.

 

변수는 프로그램 내에서 세 단계를 거친다.

  1. 선언: 변수를 실행 컨텍스트의 변수 객체에 등록한다. 이 변수 객체는 스코프가 참조하는 대상이 된다.
  2. 초기화: 변수 객체에 등록된 변수를 위한 공간을 메모리에 확보한다. 이 단계에서 변수는 undefiend로 초기화된다.
  3. 할당: undefined로 초기화된 변수에 실제 값을 할당한다.

이 세 단계를 기억하며, var과 let, const의 차이를 알아보자

 

var로 선언한 변수는 선언과 초기화 단계가 동시에 이뤄진다.

즉, 스코프에 변수를 등록(선언)하고, 메모리에 변수를 위한 공간을 확보한 후, undefined로 초기화한다.

따라서, 변수 선언문 이전에 변수에 접근하여도 스코프에 변수가 존재하기 때문에 에러가 발생하지 않는다. 다만, undefined가 반환된다. 이후 변수 할당문에 도달하면 비로소 값이 할당된다.

 

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

즉, 스코프에 변수를 등록(선언)하지만 초기화 단계는 변수 선언문에 도달했을 때(코드 실행 후) 이루어진다.

따라서, 초기화 이전에 변수에 접근하려고 하면 참조 에러가 발생한다. 이는 변수를 위한 메모리 공간을 확보하는 초기화가 이루어지지 않았기 때문이다.

 

결론적으로, let과 const로 선언된 변수는 스코프의 시작 지점부터 초기화 지점까지는 변수를 참조할 수 없다.

이 지점 차이를 일시적 사각지대(Temporal Dead Zone, TDZ)라고 부른다. 이 지점의 변수들은 메모리가 아직 할당되지 않은 상태이므로 접근을 시도한다면 ReferenceError가 발생하게 된다.

 

 

생각 정리

  • 호이스팅은 에러 현상이 아니라, 필연적 작용이다.
  • 호이스팅은 물리적으로 최상단으로 올라가는 것이 아니라, 순서가 끌어올려지는 것이다.
  • 애초에 변수 선언을 코드 상단부에 적자.
  • var 대신 let과 const를 사용하자.

 

 

감사한 레퍼런스

'JavaScript' 카테고리의 다른 글

DOM(문서 객체 모델) - 문서를 조작하자  (0) 2023.05.14