호이스팅 (Hoisting)
Hoisting 🤔
호이스팅(Hoisting)은 변수나 함수의 선언문을 스코프의 최상단으로 끌어올리는 자바스크립트의 특별한 동작입니다. 이를 이해하기 위해서는 자바스크립트 엔진의 동작 과정이 소스를 평가하는 과정과 실행하는 런타임 과정으로 나뉘는 것을 알아야 합니다. 자바스크립트 엔진은 코드를 실행하기 전에 필요한 정보, 예를 들어 변수 선언을 포함한 모든 선언문(var, let, const, function, class 등)을 읽어 메모리에 등록합니다. 메모리에 등록된 식별자들은 평가 과정이 끝나고, 런타임이 진행되면서 값이 할당됩니다.
다음의 코드는 호이스팅이 발생합니다.
console.log(x); // undefined
var x = 'hello';
console.log(x); // hello
var 키워드로 선언한 변수는 평가 과정에 스코프의 최상단에 끌어올려진 후 초기화가 함께 진행됩니다. 그렇기 때문에 코드 상의 선언부 이전에도 참조가 가능한 것이고, 이 때는 값을 할당하기 전이므로 undefined가 출력됩니다.
그림으로 이해하기
호이스팅이 진행되는 과정을 그림으로 이해해 봅시다.
자바스크립트 엔진은 소스코드 실행에 앞서 평가 과정을 먼저 진행하게 됩니다. 최초로 sum이라는 함수의 선언문을 읽어, 식별자를 메모리에 등록하게 되는데, 선언형 함수의 경우는 본체까지 함께 등록하기 때문에 초기값이 본체의 내용과 일치합니다.
이어서 const와 let으로 선언된 식별자(name, info)를 메모리에 등록하고, 값은 선언은 되었지만 초기화가 되지 않았음을 의미하는 uninitialized 상태로 둡니다.
var로 선언된 변수도 메모리에 식별자를 먼저 등록하지만, const와 let으로 선언된 두 식별자와 달리 등록과 함께 undefined로 초기화합니다. 평가가 끝났으니 코드를 한 줄 씩 실행하는 런타임 과정도 계속해서 살펴보겠습니다.
소스 평가 과정에서 코드에 변수나 함수의 선언 부분이 있으면, 런타임 시 참조하기 위해 메모리에 먼저 등록하는 것을 알았습니다. 그렇기 때문에 선언문이 참조하는 부분보다 아래에 있더라도, 메모리에는 등록이 되어있기 때문에 참조할 수 있습니다. 위 그림에서 함수는 식별자와 본체가 평가 과정에 함께 등록되기 때문에, 올바른 결과가 출력되는 것을 확인할 수 있습니다.
var로 선언된 변수는 평가 과정에서 undefined로 초기화가 함께 이루어지기 때문에 역시 참조 가능합니다.
하지만 let과 const로 선언된 변수의 경우는 var로 선언된 변수와 다르게 동작합니다. 이 둘은 평가 과정에서 초기값이 결정되지 않은 상태(uninitialized)로 남게 되는데, 이는 변수의 선언 단계와 초기화 단계 사이에 TDZ(Temporal Dead Zone)라는 영역이 존재하기 때문입니다. 이 영역은 변수가 실제 초기화 구문을 만나기 전까지는 참조할 수 없도록 제한합니다. 그렇기 때문에 결과로 RefernceError가 출력됩니다. TDZ의 존재 덕에 할당되지 않은 변수를 참조하는 위험을 사전에 방지할 수 있습니다.
원래라면 에러가 발생해서 실행을 멈춰야 하지만, 여기서는 그림으로 남은 과정을 마저 확인하겠습니다.
남은 부분들은 메모리에 등록된 식별자에 값을 할당하는 할당문입니다. 런타임 도중 할당문을 만나게 되면 식별자에 값을 할당하게 되고, let과 const로 선언된 변수들은 이 시점 이후부터 올바르게 참조 가능합니다.
Recap 🎉
- 호이스팅은 자바스크립트 엔진의 동작 과정이 나뉘는 데에서 발생하는 특징이다.
- 평가 과정에서 선언형 함수는 식별자와 본체가 함께 등록된다.
- 평가 과정에서 let과 const로 선언된 변수는 식별자가 등록되지만 초기값은 정해지지 않는다.
- 평가 과정에서 var로 선언된 변수는 식별자가 등록되고, undefined로 초기화된다.
- 런타임 과정에서 변수의 값들이 할당되고, 함수가 실행된다.
References 📖
'🌈 기술스택 > JavaScript' 카테고리의 다른 글
자기 자신을 가리키는 값 this (0) | 2021.10.03 |
---|---|
자바스크립트 코드의 유효 범위 Scope (0) | 2021.10.03 |
얕은 복사 & 깊은 복사 (0) | 2021.10.03 |
유사 배열 객체 만들기 (0) | 2021.10.02 |
일급 객체 (First Class Object) (0) | 2021.10.02 |
댓글
이 글 공유하기
다른 글
-
자바스크립트 코드의 유효 범위 Scope
자바스크립트 코드의 유효 범위 Scope
2021.10.03 -
얕은 복사 & 깊은 복사
얕은 복사 & 깊은 복사
2021.10.03 -
유사 배열 객체 만들기
유사 배열 객체 만들기
2021.10.02 -
일급 객체 (First Class Object)
일급 객체 (First Class Object)
2021.10.02