JavaScript에서 호이스팅(hoisting)이란
인터프리터가 변수와 함수의 메모리 공간을 선언전에 미리 할당하는 것
함수가 실행되기 전에, 안에있는 변수들을 범위의 최상단으로 끌어올리는 것
Javascript의 경우 함수의 코드를 실행하기 전에 함수 선언에 대한 메모리부터 할당한다.
따라서 함수를 호출하는 코드를 함수 선언보다 앞서 배치할 수 있다.
function catName(name) {
console.log('제 고양이의 이름은 ' + name + '입니다.');
}
catName('호랑이');
/*
결과 : '제 고양이의 이름은 호랑이입니다.'
*/
위의 코드가 일반적인 코드 작성 순서이다.
catName('호랑이');
function catName(name) {
console.log('제 고양이의 이름은 ' + name + '입니다.');
}
/*
결과 : '제 고양이의 이름은 호랑이입니다.'
*/
위 처럼 호출이 함수 자체보다 앞서 존재하는 경우 역시 코드는 동작한다.
이것이 JavaScript에서 실행 맥락이 동작하는 방식이다.
호이스팅은 다른 자료형과 변수에도 잘 작동한다.
변수를 선언하기 전 먼저 초기화하고 사용할 수 있는 것이다.
let과 const로 선언한 변수도 호이스팅 대상이지만, var와 달리 호이스팅 시 undefined로 변수를 초기화하지는 않는다.
변수의 초기화를 수행하기 전에 읽는 코드가 먼저 나타나면 예외가 발생한다.
let 변수는 초기화하기전에 읽거나 쓸 수 없다.
(선언 구문에 초기 값을 지정하지 않는 경우 undefined로 초기화 함)
초기화 전에 접근을 시도하면 ReferenceError가 발생한다.
(var의 경우, 선언 전에 접근할 시 iundefined)
호이스팅~TDZ~선언
변수 스코프의 맨 위에서 변수의 초기화 완료 시점까지의 변수는 "시간상 사각지대"(TDZ)에 들어간 변수라고 표현한다.
function do_something() {
console.log(bar); // undefined
console.log(foo); // ReferenceError
var bar = 1;
var foo = 2;
}
'Temporal' Dead Zone 즉, 시간상 사각지대인 이유는,
사각지대가 코드의 작성 순서(위치)가 아니라 코드의 실행 순서(시간)에 의해 형성되기 때문이다.
// TDZ가 스코프 맨 위에서부터 시작
const func = () => console.log(letVar); // OK
// TDZ 안에서 letVar에 접근하는 경우 -> ReferenceError
let letVar = 3; // letVar의 TDZ 종료
func(); // TDZ 밖에서 호출
let 변수 선언 코드가 그 변수에 접근하는 함수보다 아래에 위치하지만, 함수의 호출 시점이 사각지대 밖이므로 정상 동작한다.
참고
MDN web docs