호이스팅에 대해 알아보기 전에, 먼저 변수가 생성되는 과정을 살펴보자.
선언 - 초기화 - 할당
변수는 다음의 세 단계를 거쳐 생성된다.
- 선언
해당 변수를 스코프에 등록하는 과정이다. 키워드 var, let, const 중 하나를 통해 이루어진다. - 초기화
해당 변수를 위한 공간을 메모리에 확보한다. 이때 변수의 값은 임의로 undefined로 할당된다.
var 키워드를 사용한 경우 초기화 과정은 선언 과정과 함께 이루어지고, let 또는 const 키워드를 사용한 경우 초기화 과정은 선언 과정과 별개로 이루어진다. - 할당
undefined로 초기화된 변수에 할당 연산자(=)를 사용하여 실제 값을 할당한다.
호이스팅(Hoisting)이란?
이제 이 이미지를 보자.
먼저 a의 경우, a는 선언된 적이 없으니 ReferenceError가 뜬다.
그리고 맨 아래의 c의 경우, c를 선언하기도 전에 참조하려고 했으니 ReferenceError가 뜨는 건 당연해보인다.
그런데 b의 경우, b도 c와 마찬가지로 b를 선언하기 전에 참조하려고 했으니 ReferenceError가 떠야 할 것 같지만 undefined가 참조된다! b의 선언-초기화-할당 과정 중에서 선언-초기화 까지의 과정이 우리가 모르는 사이에 이미 이루어졌다는 것을 의미한다. 이게 어떻게 된 일일까?
자바스크립트 엔진은 실행 컨텍스트(코드가 실행되는 환경이라는 추상적인 개념이다)를 위해, 코드를 실행하기 전에 해당 스코프에 선언된 변수들을 모두 등록한다. 앞으로 선언될 변수들의 '선언' 과정들만 모아서 미리 해두는 거다. 그래서 마치 변수들의 선언 과정만 스코프의 최상단에 있는 것처럼 동작하게 되고, 이를 호이스팅(Hoisting)이라고 부른다.
여기에서 var 키워드와 let/const 키워드의 차이가 발생한다. var 키워드로 선언된 변수는 선언 과정과 초기화 과정이 한 번에 이루어진다. 그래서 변수가 호이스팅될 때, 선언 과정뿐만 아니라 undefined로 초기화하는 과정까지 모두 호이스팅된다(= 해당 블록의 맨 위에 있는 것처럼 동작한다).
반면 let/const 키워드로 선언된 변수는 선언 과정과 초기화 과정이 별개로 이루어지기 때문에, 선언 과정만 호이스팅되고, 초기화 과정은 코드를 실행하다가 해당 선언문을 만났을 때에야 비로소 이루어진다. 초기화 과정을 마치기 전에 해당 변수에 접근을 시도하면, 아직 메모리에 해당 변수의 공간을 할당받지 못한 상태기 때문에 ReferenceError가 난다.
TDZ
a와 c는 둘 다 ReferenceError가 났지만, a는 정말로 선언된 a가 없어서(...) 에러가 났던 것이고, c는 선언은 되었지만 아직 초기화되지 않은, 일종의 사각지대에 있기 때문에 에러가 났던 것이다. 이 사각지대 구간을 TDZ 구간(Temporal Dead Zone)이라고 한다.
TDZ의 범위는 스코프의 시작 지점 ~ 해당 변수가 초기화되는 지점이다. var 키워드로 선언된 변수는 선언 과정과 초기화 과정이 한번에 이루어지기 때문에 TDZ가 존재하지 않는 것으로 간주된다.
정리
1. 변수가 생성될 때 선언-초기화-할당 과정을 거친다.
2. 자바스크립트에서 변수들은 선언 과정만 미리 실행된다. 그래서 선언 과정이 마치 해당 스코프의 최상단에 있는 것처럼 동작하고, 그걸 호이스팅이라고 부른다.
3. 모든 변수에는 호이스팅이 일어난다. 특히 var로 선언된 변수는 호이스팅에 초기화 과정이 동반되어 눈에 잘 띈다(let/const 키워드가 호이스팅이 안 일어나는 게 아님!).
4. TDZ 구간은 선언 과정과 초기화 과정 사이의 사각지대를 의미한다. TDZ에서 해당 변수에 접근하려고 하면 에러가 발생한다.
'JavaScript & React' 카테고리의 다른 글
02-8 배열 함수 (1) | 2023.11.20 |
---|---|
02-7 라이브러리 의존성 관리 (0) | 2023.10.30 |
02-6 객체 확장 표현식과 구조 분해 할당 (0) | 2023.10.30 |
02-5 화살표 함수 (0) | 2023.10.01 |
02-4 클래스 (0) | 2023.09.30 |