개발 기술/개발 이야기

[JS] 호이스팅(hoisting)

by GicoMomg (Lux) 2021. 12. 21.

1) 호이스팅이란?

(1) 호이스팅 개념

  • 변수&함수 선언만 해당 스코프의 최상단으로 끌어올려지는 걸 호이스팅이라고 한다.
  • 아래와 같이 변수를 선언해도 상단에서 변수 참조가 가능하다.
console.log(a)
var a;


  • 단, 변수의 선언만 끌어올려지므로 값을 할당해도 결과는 undefined가 된다.
console.log(a)
var a = 1;



2) 호이스팅이 발생하는 이유

(1) 왜 발생할까?

🏃🏻 자바스크립트 엔진에서 변수를 생성하는 단계를 먼저 살펴보자

  • 자바스크립트 엔진에서 변수는 선언 → 초기화 → 할당을 거쳐 생성된다.
단계 설명
선언 단계 변수를 실행 컨텍스트(실행 코드에 제공할 정보 객체)의 변수 객체에 등록한다.
초기화 단계 변수 객체에 등록된 변수를 위한 메모리 공간을 확보한다. (이때, undefined로 초기화됨)
메모리가 할당되면 메모리 참조를 통해 변수에 접근할 수 있다.
할당 단계 사용자가 정의한 값을 변수에 할당해준다.

  • 자바 스크립트 엔진은 코드를 실행하기 전에 실행 컨텍스트에 등록된 변수 객체에 접근할 수 있다.
  • var의 경우 변수 선언&초기화가 함께 진행되므로, 변수 객체 등록과 동시에 메모리 공간도 할당 받는다.
  • 그렇기 때문에 메모리를 할당받은 상태이므로 호이스팅시 메모리 참조를 통해 변수 접근이 가능하다.
console.log(a);  // 변수 접근 가능
var a;           // 실행 컨텍스트에 등록 & 메모리 할당 받음

  • let의 경우, 선언과 초기화를 각각 진행한다.
  • 선언 단계에서 실행 컨텍스트에 등록은 했지만, 메모리를 할당받지 못해 접근이 불가능한 상태이다.
  • 결국, 메모리를 할당받지 못해 참조할 메모리가 없으므로 ReferenceError가 발생한다.
console.log(a); // 변수 접근 불가능
let a;          // 실행 컨텍스트에 등록 & 메모리 할당 못 받음


  • 함수 선언문의 경우, 선언 & 초기화 & 할당이 동시에 진행되므로 호이스팅은 물론 실행도 가능하다.
print()  // a

function print() {
  console.log('a')
}

  • 단, 아래와 같이 함수표현식을 사용한다면 호이스팅이 불가하다.
print()  // error

const print = () => {
  console.log('a')
}



3) let, const는 호이스팅이 불가하다?

🏃🏻 let, const는 왜 ReferenceError가 발생할까? TDZ와 함께 알아보자.

  • TDZ(Temporal Dead Zone)는 선언 ~ 초기화 단계 사이를 이야기한다.
  • 아래와 같이 선언보다 먼저 호출하면 ReferenceError가 발생하는데, 이를 TDZ에 걸렸다고 얘기한다.
console.log(a)  
// error: Uncaught ReferenceError: Cannot access 'a' before initialization

let a = 12;

const 선언방식을 예로 보자. 우리가 예상했던 대로 ReferenceError가 발생한다.

console.log(a); // ReferenceError
const a = '1';

  • const a = '1' 전까지, 변수 a 는 TDZ 구간에 놓여 있다.
  • 그 이유는 var과 달리 const는 코드를 실행하는 시점에서는 실행 컨텍스트 추가만 됐기 때문이다.
  • 그러므로 console.log(a) 입장에서는 변수 a는 선언~초기화 사이 단계인 것이며, 이 때는 메모리 할당을 받지 못해 참조할 메모리가 없으므로 ReferenceError: Cannot access 'a' before initialization 자바스크립트 에러가 발생한다.

🏃🏻 단, 참조할 메모리가 없는 것이지 호이스팅이 발생하지 않는 건 아니다.



반응형

댓글