자바스크립트에서 호이스팅(Hoisting)은 변수, 함수 선언이 해당 스코프의 최상단으로 끌어올려진 것처럼 동작하는 메커니즘입니다. 이는 자바스크립트가 실행되기 전에 변수와 함수 선언을 메모리에 먼저 할당하기 때문에 발생합니다. 호이스팅은 변수를 선언하기 전에 사용할 수 있게 해주는 것처럼 보이지만, 실제로는 선언만 끌어올려지고 초기화는 그렇지 않기 때문에 주의가 필요합니다.
1. 변수 호이스팅
1.1 var 변수 호이스팅
var
로 선언된 변수는 호이스팅되며, 선언과 초기화가 분리되어 처리됩니다. 선언은 스코프의 최상단으로 끌어올려지지만, 초기화는 실제 코드에 도달했을 때 이루어집니다.
console.log(hoistedVar); // undefined
var hoistedVar = 'I am hoisted';
console.log(hoistedVar); // I am hoisted
위 코드에서 hoistedVar
선언은 스코프의 최상단으로 끌어올려지지만, 초기화는 var hoistedVar = 'I am hoisted';
부분에서 이루어집니다. 따라서, 첫 번째 console.log
에서는 undefined
가 출력됩니다.
1.2 let과 const 변수 호이스팅
let
과 const
로 선언된 변수도 호이스팅되지만, 초기화는 호이스팅되지 않습니다. let
과 const
변수는 “일시적 사각지대(TDZ, Temporal Dead Zone)”에 놓이게 되어, 선언 전에 접근하려고 하면 참조 에러가 발생합니다.
console.log(hoistedLet); // Uncaught ReferenceError: Cannot access 'hoistedLet' before initialization
let hoistedLet = 'I am hoisted with let';
console.log(hoistedConst); // Uncaught ReferenceError: Cannot access 'hoistedConst' before initialization
const hoistedConst = 'I am hoisted with const';
위 코드에서 hoistedLet
과 hoistedConst
는 선언 전에 접근하려고 하면 참조 에러가 발생합니다. 이는 let
과 const
변수가 호이스팅되지만, 초기화가 이루어지기 전에 접근할 수 없기 때문입니다.
2. 함수 호이스팅
함수 선언은 변수 선언과 달리 전체가 호이스팅됩니다. 즉, 함수 선언 전체가 스코프의 최상단으로 끌어올려져서 함수 선언 전에 호출이 가능합니다.
hoistedFunction(); // I am a hoisted function
function hoistedFunction() {
console.log('I am a hoisted function');
}
위 코드에서 hoistedFunction
은 함수 선언 전에 호출할 수 있으며, 정상적으로 작동합니다.
2.1 함수 표현식의 호이스팅
함수 표현식은 변수 선언처럼 동작하여, 선언은 호이스팅되지만 초기화는 호이스팅되지 않습니다.
console.log(hoistedFunction); // undefined
hoistedFunction(); // Uncaught TypeError: hoistedFunction is not a function
var hoistedFunction = function() {
console.log('I am not hoisted');
};
위 코드에서 hoistedFunction
은 변수 선언처럼 호이스팅되지만, 초기화는 실제 코드에 도달했을 때 이루어집니다. 따라서, 함수 표현식을 선언하기 전에 호출하면 TypeError
가 발생합니다.
3. 클래스 호이스팅
클래스는 let
과 const
처럼 호이스팅되지만 초기화되기 전에는 접근할 수 없습니다.
const instance = new MyClass(); // ReferenceError: Cannot access 'MyClass' before initialization
class MyClass {
constructor() {
this.name = 'MyClass';
}
}
위 코드에서 MyClass
는 호이스팅되지만 초기화되기 전에는 사용할 수 없으므로 참조 에러가 발생합니다.
4. 호이스팅의 실제 예제
다음은 호이스팅이 실제로 어떻게 작동하는지를 보여주는 예제입니다.
console.log(a); // undefined
var a = 5;
function example() {
console.log(b); // undefined
var b = 10;
if (true) {
var c = 20;
let d = 30;
}
console.log(c); // 20
console.log(d); // ReferenceError: d is not defined
}
example();
위 코드에서 a
와 b
는 var
로 선언되었기 때문에 호이스팅됩니다. 따라서 초기화 전에 접근하면 undefined
가 출력됩니다. c
는 블록 스코프와 상관없이 함수 스코프에 속하기 때문에 함수 내 어디서든 접근할 수 있습니다. 그러나 d
는 let
으로 선언되었기 때문에 블록 스코프를 가지며, 블록 외부에서는 접근할 수 없습니다.
5. 호이스팅과 함수 표현식
함수 표현식은 변수 호이스팅의 규칙을 따릅니다. 따라서 함수 표현식으로 정의된 함수는 선언 전에 호출할 수 없습니다.
hoistedFunction(); // TypeError: hoistedFunction is not a function
var hoistedFunction = function() {
console.log('I am a hoisted function expression');
};
위 코드에서 hoistedFunction
은 변수로 호이스팅되지만, 함수로 초기화되기 전에 호출하려고 하면 TypeError
가 발생합니다.
호이스팅은 자바스크립트의 중요한 특성이며, 이를 이해하면 코드의 동작 방식을 더 잘 예측하고 디버깅할 수 있습니다. 특히, let
과 const
의 호이스팅 동작을 이해하면 변수 선언 및 초기화와 관련된 오류를 줄일 수 있습니다.