: Hoist(:끌어 올리다) 에서 비롯된 용어로 인터프리터가 변수와 함수의 메모리 공간을 선언 전에 미리 할당하는 것 뜻합니다.
인터프리터
프로그래밍 언어의 소스 코드를 바로 실행하는 컴퓨터 프로그램 또는 환경을 말한다.
var
키워드로 선언한 변수의 경우 호이스팅 시 undefined
로 변수를 초기화합니다. 반면 let
과 const
로 선언한 변수의 경우는 초기화하지 않습니다.
JavaScript는 함수의 코드를 실행하기 전에 함수 선언에 대한 메모리부터 할당합니다. (= 호이스팅합니다) 덕분에 함수를 호출하는 코드를 함수 선언보다 앞서 배치할 수 있습니다.
함수 호이스팅은 내부적으로 다른 무엇보다 가장 먼저 이루어집니다. 그리고 함수 호이스팅은 함수 선언문에만 해당됩니다.
함수의 선언문은 식별자가 변수 객체에 수집될 때 부가적으로 해당 함수 참조에 대한 초기화까지 자동으로 이루어집니다. 이로 인하여 선언된 함수는 상단에서 참조, 호출이 가능합니다.
함수 표현식은?
함수 표현식은 결국 함수를 변수에 할당하는 것이므로 변수 호이스팅의 사례로 볼 수 있습니다.
변수는 프로그램 내에서 크게 세 가지 단계를 거칩니다.
함수 호이스팅에서 그랬듯이 변수 또한 선언과 초기화를 해주어야만 값의 참조 및 할당이 가능합니다. 다만 변수 선언 방식(키워드)에 따라 선언, 초기화의 시점이 달라질 가능성이 있습니다.
var
: 호이스팅이 발생하면 선언과 초기화가 거의 동시에 이루어집니다. 해당 변수에 대한 메모리가 실행 시점의 스코프 최상단에 존재하기 때문에 선언부 위치에 상관없이 참조, 할당이 가능합니다.
let
, const
: 호이스팅이 발생하면 선언만 이루어지고 실행 지점에서 실질적인 선언부를 만날 때까지 초기화가 이루어지지 않습니다. 이 간극만큼 해당 변수에 대한 메모리가 존재하지 않기에 선언부 상단에서 참조, 할당이 불가능합니다.
let
, const
가 동작하는 과정에서 스코프의 진입지점과 해당 식별자의 실질적 선언부 사이를 일시적 사각지대, TDZ(Temporal Dead Zone) 라고 합니다. 이 시점에서 변수는 존재하지만, 초기화가 이루어지지 않았습니다.
// 1번 코드
function myName(name) {
console.log("제 이름은 " + name + "입니다");
}
myName("허정우");
// 2번 코드
myName("허정우");
function myName(name) {
console.log("제 이름은 " + name + "입니다");
}
// 결과: 제 이름은 허정우입니다
1번 코드와 2번 코드는 함수 호출과 선언의 시점이 다르지만 같은 방식으로 동작하는 것을 볼 수 있습니다.
함수 호출이 함수 자체보다 앞서 존재하여도 코드가 동작합니다. 이것이 JavaScript에서 실행 맥락이 동작하는 방식입니다.
호이스팅은 다른 자료형과 변수에도 작동합니다. 변수를 선언하기 전에 먼저 초기화하고 사용할 수 있는 것입니다.
JavaScript는 초기화를 제외한 선언만 호이스팅합니다. 변수를먼저 사용하고 그 후에 선언 및 초기화가 나타나면, 사용하는 시점의 변수는 기본 초기화 상태입니다.
console.log(num); 출력
var num; // 선언
num = 10; // 초기화
// 호이스팅한 var선언으로 인해 undefined
console.log(num);
num = 10; // 초기화
// 선언이 없고 초기화만 존재, 호이스팅 X
// 변수 읽기 시도 -> ReferenceError 예외 발생
Reference.
MDN
호이스팅의 오해와 진실