호이스팅(hoisting)은 코드 블록에 선언된 변수선언 및 함수선언을 코드 블록의 최상단으로 끌어 올리는 것을 말하며 실제로 끌어올려지지않지만 옮긴 것처럼 동작하는 특성
을 말한다.
console.log(foo); // undefined
var foo = 5;
위의 코드에서 var 키워드 선언된 변수
가 있다. 실행결과는 error가 나올 것 같지만 undefined라는 값이 출력이 되었다. 이는 호이스팅이 일어났기 때문이다. 위의 코드를 호이스팅으로 인해 재해석해보자면 아래와 같이 간주할 수 있다.
var foo;
console.log(foo); // undefined
foo = 5;
그렇다면 ES6에서 추가된 let과 const 키워드
로 선언된 변수도 호이스팅이 일어날까?
console.log(foo); // ReferenceError
let foo = 5;
위의 코드를 실행해보면 ReferenceError가 출력된다.
호이스팅이 된다고 했는데 왜 ReferenceError가 날까?
let과 const로 선언한 변수
는 var와 다르게 초기화(or 할당)가 되기전까지 TDZ(Temporal Dead Zone)
라는 곳에 빠져 초기화(or 할당)가 될 때까지 참조가 불가능하기 때문에 ReferenceError가 출력되는 것이다.이를 좀 더 이해하기 위해서는 이전에 작성한 ✔️ 실행 컨텍스트의 생성의 LexicalEnvironment와 VariableEnvironment 부분을 참고하면 좋다.
❓ 참조
TDZ(Temporal Dead Zone) 란?
TDZ(Temporal Dead Zone) 란, 한글로 직역하자면 일시적인 사각지대란 뜻으로
스코프의 시작 지점부터 초기화 시작 지점까지의 구간을 TDZ(Temporal Dead Zone)라고 한다.
one(1); // 1
// 함수 선언식 - Function Declarations
function one(number) {
console.log(number);
}
위의 코드는 함수 선언식으로 작성된 코드이다.
이때도 var 키워드로 선언된 방식과 같이 문제 없이 실행이 된다.
two(2); // TypeError: two is not a function
// 함수 표현식 - Function Expressions
var two = function(number) {
console.log(number);
}
/* 호이스팅이 일어났을 때 아래의 모습일 것이다.
var two;
two(2); // TypeError: two is not a function
// 함수 표현식 - Function Expressions
two = function(number) {
console.log(number);
}
*/
two(2); // ReferenceError: Cannot access 'two' before initialization
// 함수 표현식 - Function Expressions
let two = function(number) {
console.log(number);
}
/* 호이스팅이 일어났을 때 아래의 모습일 것이다.
let two; < uninitialized >
two(2); // ReferenceError: Cannot access 'two' before initialization
// 함수 표현식 - Function Expressions
two = function(number) {
console.log(number);
}
*/
위의 코드들은 함수 표현식으로 작성된 코드이다.
함수 표현식의 경우에는 변수 호이스팅
이 발생하기 때문에
var로 선언되었을 때
는 undefined이기 때문에 함수가 아니라는 TypeError가 발생
하며
let 또는 const로 선언되었을 때
는 TDZ로 인한 ReferenceError가 발생
한다.
호이스팅의 과정은 실행 컨텍스트를 이해하고 나면 수월할 것이다.