코드 블록에 선언된 변수선언 및 함수선언을 코드 블록의 최상단으로 끌어 올리는 것을 말하며 실제로 끌어올려지지 않지만 옮긴 것처럼 동작하는 특성이다.
호이스팅의 종류에는 var,let,const 호이스팅, 함수 선언식, 함수 표현식의 호이스팅이 있다. 호이스팅이 된다 하더라도 각각 차이점이 존재한다.
var는 오로지 함수의 코드 블록만을 지역 스코프로 인정합니다. 따라서 함수 외부에서 var 키워드로 선언한 변수는 코드 블록 내에서 선언해도 모두 전역 변수가 된다.
또한 var는 재할당, 재선언이 가능하며, 변수를 선언하기 전에 참조할 수 있고, 그 값은 undefined이다.
예시
function introduce() {
alert(phrase); // undefined
var phrase = "I'm jinwon";
}
introduce();
function introduce() {
var phrase;
alert(phrase); // undefined
phrase = "I'm jinwon";
}
introduce();
let은 var 와는 달리, 모든 코드 블록을 지역 스코프로 인정한다. 또한, 재선언은 불가능하지만, 재할당은 가능하며, 선언 전에 사용하면 초기화 되기 전까지 TDZ에 빠져 참조가 불가능하기 때문에 ReferenceError가 출력된다.
const 키워드로 선언한 변수는 반드시 선언과 동시에 초기화해야 한다. 즉, 재선언,재할당이 불가능하다. let과 마찬가지로 초기화 되기 전까지 TDZ에 빠져 참조가 불가능하기 때문에 ReferenceError가 출력된다.
예시
function introduce() {
alert(phrase); // Uncaught ReferenceError: Cannot access 'phrase' before initialization at introduce
let phrase = "I'm jinwon";
}
introduce();
자바스크립트에서 변수를 메모리에 할당하는 과정은 크게 3단계로 진행된다.
첫번째로, 실행 컨텍스트 변수 객체에 등록하는 선언 단계, 두번째로, 변수 객체에 대한 메모리 할당 및 변수를 undefined로 초기화하는 초기화 단계, 마지막으로 undefined로 초기화 된 변수에 값 할당하는 할당 단계다.
각 호이스팅마다 단계를 진행하는 방식이 다르기 때문에 각각 차이가 존재한다.
앞서 설명한 변수의 메모리 할당 과정을 바탕으로 설명하자면, var는 1,2단계가 동시에 진행되면서 호이스팅이 된다.
하지만, const/let은 1,2단계가 분리되어 진행되므로 1단계만 진행되면서 호이스팅이 되기 때문에 이런 차이가 발생한다. 호이스팅이 된 시점을 봐보면 var의 경우 변수에 undefined가 할당되어 있는 상태고, let/const은 undefined로 초기화되지 않았으므로 ReferenceError가 발생한다.
함수 선언식의 경우 함수의 선언이 호이스팅되어 선언 전에 사용이 가능하다.
함수 표현식의 경우 변수 호이스팅이 발생한다. 따라서, var로 선언되었을 때는 undefined이기 때문에 함수가 아니라는 TypeError가 발생하며, let 또는 const로 선언되었을 때는 TDZ로 인한 ReferenceError가 발생한다.
https://velog.io/@kich555/Lexical-Environment-Scope-TDZ-wqlit1i9
Ilya Kantor.『코어 자바스크립트』