호이스팅(Hoisting)이란 자바스크립트 인터프리터가 변수와 함수 안에 있는 선언들을 모두 해당 함수 유효 범위의 최상단에 선언하는 것을 말한다. 하지만 주의해야 할 점은 실제로 위치가 옮겨지는 것이 아니라 그렇게 된 것처럼 실행이 된다는 뜻이라는 것을 염두에 두어야 한다. 즉, 선언이 코드 실행보다 먼저 메모리에 저장되는 과정으로 인해 야기되는 현상이다.
변수가 생성되는 절차는 아래와 같다.
1단계: 선언 단계(Declaration phase)
- 변수를 실행 컨텍스트의 변수 객체에 등록한다.
- 이 변수 객체는 스코프가 참조하는 대상이 된다.
2단계: 초기화 단계(Initialization phase)
- 변수 객체에 등록된 변수를 위한 공간을 메모리에 확보한다.
- 이 단계에서 변수는 undefined로 초기화 된다.
3단계: 할당 단계(Assignment phase)
- undefined로 초기화된 변수에 실제 값을 할당한다.
하지만 위 단계를 통해 선언이 끌어올려지는 것이지 할당이 우선적으로 이루어지는 것은 아니다.
유효 범위는 함수 블록 {} 안에서 유효하며 함수 내에서 아래쪽에 존재하는 내용 중 필요한 값들을 끌어올리는 것이다. 다시 한 번 강조하자면 실제로 코드가 끌어올려지는 건 아니고, 자바스크립트 Parser 내부적으로 끌어올려서 처리하는 것이다. 실제 메모리에서는 변화가 없다.
자바스크립트의 모든 선언에는 호이스팅이 일어난다. 하지만 let, const, class를 이용한 선언문을 호이스팅이 발생하지 않는 것처럼 동작한다. var 키워드로 선언된 변수와는 달리 let 키워드로 선언된 변수를 선언문 이전에 참조하면 참조 에러(ReferenceError)가 발생한다. 이는 let 키워드로 선언된 변수는 스코프의 시작에서 변수의 선언까지 일시적 사각지대(Temporal Dead Zone; TDZ)에 빠지기 때문이다.
아래는 호이스팅을 테스트해볼 수 있는 js코드이다.
// hoisting
var myName = "hi";
var myName = function myName() {
function myName() {
console.log("alien");
}
function yourName() {
console.log("everyone");
}
var yourName = "bye";
console.log(typeof myName);
console.log(typeof yourName);
참고 자료
https://hanamon.kr/javascript-%ED%98%B8%EC%9D%B4%EC%8A%A4%ED%8C%85%EC%9D%B4%EB%9E%80-hoisting/