2 min to read
[ECMAScript] 호이스팅(Hoisting)
JavaScript에서 호이스팅(hoisting)이란, 인터프리터가 변수와 함수의 메모리 공간을 선언 전에 미리 할당하는 것을 의미한다.
즉, 변수나 함수 선언을 함수 스코프의 맨 위로 이동하는 것을 말한다.
변수 호이스팅
변수는 아래와 같이 3단계에 걸쳐 생성된다.
- 선언 - 변수를 선언하여 실행 컨텍스트의 변수 객체에 등록한다.
- 초기화 - 변수 객체에 대한 메모리를 할당하고, 변수는 undefined 로 초기화 된다.
- 할당 - 초기화된 변수에 실제 값을 할당한다.
var
은 변수의 선언과 초기화가 동시에 일어난다. 따라서 선언문 이전에 해당 변수에 접근하여도 호이스팅에 의하여 에러가 발생하지 않고, undefined 를 반환한다.
이를 변수 호이스팅(Variable Hoisting) 이라고 한다.
console.log(foo); // undefined
var foo;
console.log(foo); // undefined
foo = 1;
console.log(foo); // 1
let
은 var 과 달리 선언과 초기화가 분리되어 발생한다. 즉, 스코프에 변수를 선언하지만 초기화는 변수의 선언문에 도달했을 때 이루어진다.
그렇기 때문에 초기화 이전에 변수에 접근한다면 참조 에러가 발생하게 된다. 즉, 스코프의 시작 지점부터 변수 초기화 시작 지점까지는 변수를 참조할 수 없게 되는데, 이를 일시적 사각지대(TDZ)
라고 한다.
function do_something() {
console.log(bar); // undefined
console.log(foo); // ReferenceError
var bar = 1;
let foo = 2;
}
함수 호이스팅
함수는 선언식, 표현식에 따라 호이스팅에 의한 결과가 달라진다.
함수 선언식
printName(); // minjung
function printName() {
console.log('minjung');
}
함수 선언식의 경우 호이스팅이 발생하여 함수를 최상단으로 끌어올려 printName 함수를 먼저 호출 하더라도 정상적인 결과를 출력한다.
함수 표현식
printName(); // Uncaught TypeError: printName is not a function
var printName = function() {
console.log('minjung');
}
함수 표현식의 경우 호이스팅에 의하여 var printName 은 선언과 초기화가 발생하고 할당이 되므로 아래의 코드처럼 된다.
var printName; // undefined
printName(); // Uncaught TypeError: printName is not a function
printName = function() {
console.log('minjung');
}
그러므로 printName은 호이스팅 선언과 초기화로 인해 undefined 값이 반환되므로 함수가 아니라는 오류 메세지가 발생하게 된다.
(let 으로 선언한 함수 표현식의 경우에는 변수 선언때와 동일하게 정의되지 않은 값이라는 ReferenceError
가 발생한다.)