Hoisting이란?

Hoisting은 자바스크립트 엔진이 코드를 실행하기 전에 변수와 함수 선언을 해당 스코프의 최상단으로 끌어올리는 동작 을 의미
즉, 코드에서 실제 선언된 위치와 상관없이, 선언 부분이 스코프의 “최상단”에 있는 것처럼 동작하게 만듬

선언만 호이스팅되고, 초기화(할당) 는 호이스팅되지 않음
코드 상에서 선언보다 먼저 변수를 사용해도 에러가 발생하지 않는 것처럼 보일 수 있으나, 실제로는 변수의 값이 undefined일 수 있음


변수 호이스팅(Hoisting)

자바스크립트에서 변수를 선언할 때 사용하는 키워드인 var, let, const는 각각 호이스팅 방식이 다르게 동작


var의 호이스팅

var로 선언한 변수는 함수 스코프(function scope) 를 가지며, 선언 부분이 호이스팅 됨
즉, 변수 선언이 코드의 최상단으로 끌어올려지지만, 할당은 원래 위치에서 이루어짐

console.log(myVar); // undefined (에러가 발생하지 않음)
var myVar = 10;
console.log(myVar); // 10

위코드는 아래와 같이 동작

var myVar;            // 선언이 호이스팅됨 (초기값은 undefined)
console.log(myVar);   // undefined 출력
myVar = 10;           // 할당은 원래 위치에서 수행됨
console.log(myVar);   // 10 출력


let과 const의 호이스팅

let과 const는 블록 스코프(block scope) 를 가지며, 선언 자체도 호이스팅되지만 “일시적 사각지대(Temporal Dead Zone, TDZ)” 때문에 선언 전에 접근하면 ReferenceError가 발생

console.log(myLet); // ReferenceError: Cannot access 'myLet' before initialization
let myLet = 20;

이와 같이, let과 const는 선언과 동시에 초기화되지 않으므로, 선언 이전에 변수를 사용하면 에러가 발생

*TDZ는 변수 선언이 코드 상단에 존재하더라도, 실제 초기화 시점 이전까지는 해당 변수를 참조할 수 없게 만드는 개념


함수 호이스팅

함수 선언 방식에도 호이스팅이 적용되며, 함수 선언문과 함수 표현식(또는 화살표 함수) 사이에 차이가 있음


함수 선언문(Function Declarations)

함수 선언문은 전체 함수 정의가 호이스팅 됨
즉, 함수 선언문은 코드 어디서든 호출할 수 있음

hoistedFunction(); // "함수가 호출되었습니다!"

function hoistedFunction() {
    console.log("함수가 호출되었습니다!");
}


함수 표현식과 화살표 함수

반면, 함수 표현식이나 화살표 함수로 정의한 함수는 변수에 할당되는 형태이므로, 앞서 설명한 변수 호이스팅 규칙이 적용
var로 선언했다면 초기값은 undefined 상태이고, let이나 const로 선언했다면 TDZ에 의해 초기화 전 호출 시 에러가 발생

console.log(myFunc); // undefined (var의 경우)
var myFunc = function() {
    console.log("함수 표현식입니다.");
};

myFunc(); // "함수 표현식입니다."

let을 사용한 경우

console.log(myArrowFunc); // ReferenceError: Cannot access 'myArrowFunc' before initialization
let myArrowFunc = () => {
    console.log("화살표 함수입니다.");
};


Hoisting의 동작 원리와 내부 메커니즘

자바스크립트 엔진은 코드를 실행하기 전에 컴파일 단계를 거침
이 단계에서 변수와 함수의 선언을 스코프의 최상단으로 끌어올리는 작업을 수행

컴파일 단계

  • 자바스크립트 엔진은 코드를 실행하기 전에 모든 변수와 함수 선언을 스캔
  • var와 함수 선언문은 초기값 undefined(또는 함수의 실제 구현)와 함께 할당
  • let과 const는 선언되지만, 초기화 전에 TDZ에 놓이게 됨

실행 단계

  • 코드가 위에서부터 순차적으로 실행
  • 이미 호이스팅된 변수와 함수에 접근할 수 있으나, TDZ에 있는 변수는 초기화 후에야 참조가 가능
  • 함수 선언문의 경우, 전체 구현이 호이스팅되어 있기 때문에 선언 전에 호출해도 정상 작동