자바스크립트에서 호이스팅이란, var 선언문이나 함수 선언문 등 모든 선언문이 해당 스코프의 선두로 옮겨진 것처럼 동작하는 특성을 말합니다.
여기서 var로 선언한 변수의 경우 호이스팅 시 undefined로 변수를 초기화힙니다.
즉, 변수의 선언와 초기화가 동시에 이루어 집니다.
따라서 선언부 위치에 상관없이 참조, 할당이 가능합니다.
그러나
ES6 에서 도입된 let, const로 선언한 변수의 경우 호이스팅 시 변수를 초기화 하지 않습니다.
따라서 실행시점에서 실질적인 선언부를 만날때까지 초기화는 이루어 지지 않으므로
선언부 상단에서는 참조 및 할당이 불가능합니다.
이때, 변수 스코프의 최상단에서 변수의 초기화 완료 시점까지의 간극을 시간상 사각지대 라고 말합니다.
a = 2;
var a;
console.log(a); // (1)
(1) 식의 실행결과는 무엇일까? 정상적으로(?) 2가 출력된다.
그렇다면
console.log(a); // (2)
var a = 2;
(2) 식의 실행결과는 무엇일까? 답은 2가 아니라 undefined이다.
위 두 결과를 모두 맞추었다면 당신은 호이스팅을 어느정도 이해한다고 생각한다
허나, (2)식을 2로 대답한 나는 왜 (2) 식의 답이 undefined가 나오는지 지금부터 기록할 것이다.
누군가는 var = 2
를 하나의 구문으로 볼 수 있겠지만
실제로 자바스크립트는
var a, a = 2
이렇게 두 개의 독립된 구문으로 본다.
(
그럼 여기서 어려운 질문!
대답은 자바스크립트 엔진은 인터프리팅 하기 전에 그 코드를 먼저 컴파일하기 때문
이라고 할 수 있겠다.
허나 인터프리팅이 뭔지 컴파일이 뭔지는 정확히 머리로 이해되지 않고 지금 주제와 벗어나
나중에 공부하기로 하자.
https://hashcode.co.kr/questions/7560/javascript-자바스크립트는-컴파일언어인가요-인터프리터-언어인가요
)
그래서 실제로 (2) 식은
var a;
console.log(a);
a = 2;
가 되고 할당이 되기전에 console.log을 찍으므로 undefined가 되는것이다.
여기서 var a
부분이 갑자기 맨 위로 올라가 코드 실행이 되는데
이 과정을 정리하면 변수와 함수 선언문이 선언된 위치에서 해당 스코프의 선두로 ‘옮긴것처럼' 동작하는것을 호이스팅이라고 한다.
참고로 함수 표현식은 끌어올려지지 않는다
자 그런데 돌아와서 (2) 식을 조금 비틀어 보자.
console.log(a); // (3) ReferenceError: Cannot access 'a' before initialization
let a = 2;
(2)식의 내용 중 var
에서 let
으로 바꿨을 뿐인데 왜 레퍼런스 에러가 뜰까?
바로 TDZ 때문이다.
우선 변수의 생성과정 3단계에 대해 잠깐 이야기 해보자.
var
는 호이스팅이 발생하면, 선언과 초기화가 동시에 이루어진다.
실행 시점의 스코프 최상단에서 해당 변수에 대한 메모리가 살아있기 때문에 선언부 위치에 상관 없이 참조ㅡ 할당이 가능하다.
그.러.나
let, const
는 호이스팅이 발생하면, 선언만 이루어지고 실행시점에서 실질적인 선언부를 만날 때까지 초기화는 이루어지지 않는다. 이 간극만큼 해당 변수에 대한 메모리는 존재하지 않기 때문에 선언부 상단에서 참조, 할당이 불가능하다.
이때 스코프의 진입지점과 해당 식별자의 실질적 선언부 사이를 일시적 사각지대, TDZ
라고 한다.
{
// TDZ가 스코프 맨 위에서부터 시작
const func = () => console.log(letVar); // OK
// TDZ 안에서 letVar에 접근하면 ReferenceError
let letVar = 3; // letVar의 TDZ 종료
func(); // TDZ 밖에서 호출함
}
위 코드가 정상적으로 동작하는 이유는 함수의 호출지점이 사각지대 밖이기 때문이다.
참조:
https://developer.mozilla.org/ko/docs/Glossary/Hoisting
https://meetup.toast.com/posts/86
https://poiemaweb.com/js-data-type-variable#24-변수-호이스팅variable-hoisting
https://tecoble.techcourse.co.kr/post/2021-04-25-hoisting/
https://poiemaweb.com/es6-block-scope#13-호이스팅
https://medium.com/korbit-engineering/let과-const는-호이스팅-될까-72fcf2fac365
https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Statements/let#시간상_사각지대
상의할 주제:
const, let
은 호이스팅이 되지 않는가?