JavaScript 코드를 작성하다 보면 변수나 함수를 선언하기 전에 사용했는데도 에러 없이 동작하는 경우를 마주칠 수 있습니다. 이는 JavaScript 엔진이 코드를 실행하기 전, 변수 및 함수 선언을 해당 스코프의 최상단으로 끌어올리는 것처럼 동작하기 때문이며, 이러한 현상을 **호이스팅(Hoisting)**이라고 부릅니다. 호이스팅은 JavaScript의 독특한 특징으로, 이를 정확히 이해하지 못하면 코드의 동작을 예측하기 어려울 수 있습니다.
1. var 변수와 함수 선언의 호이스팅
전통적인 var 키워드와 함수 선언문은 호이스팅이 가장 명확하게 나타나는 대상입니다.
var변수 호이스팅:var로 선언된 변수는 선언부만 스코프 최상단으로 끌어올려지며,undefined로 초기화됩니다. 할당문은 원래 위치에 그대로 남습니다.
console.log(myVar); // undefined (에러가 발생하지 않음) var myVar = 10; console.log(myVar); // 10 // 위 코드는 엔진에 의해 아래처럼 해석됩니다. // var myVar; // console.log(myVar); // myVar = 10; // console.log(myVar);
- 함수 선언문 호이스팅: 함수 선언문은 함수 전체가 메모리에 올라가므로, 선언 위치와 상관없이 스코프 내 어디서든 호출할 수 있습니다.
sayHello(); // "Hello!"
function sayHello() {
console.log("Hello!");
}
2. let, const와 TDZ (Temporal Dead Zone)
ES6에 도입된 let과 const도 호이스팅이 발생하지만, var와는 다르게 동작합니다. 이들은 선언만 끌어올려지고 초기화는 되지 않습니다. 이로 인해 스코프의 시작 지점부터 변수 선언 지점까지 일시적으로 변수에 접근할 수 없는 구간이 생기는데, 이를 **일시적 사각지대(Temporal Dead Zone, TDZ)**라고 합니다.
- TDZ 내에서 변수에 접근하려고 하면
ReferenceError가 발생합니다. 이는undefined를 반환하는var보다 훨씬 안전하고 예측 가능한 코드를 작성하게 해줍니다.
// console.log(myLet); // ReferenceError: Cannot access 'myLet' before initialization let myLet = 20; console.log(myLet); // 20
3. 함수 표현식의 호이스팅
함수 표현식(변수에 함수를 할당하는 방식)의 경우, 변수 선언 규칙에 따라 호이스팅이 적용됩니다. var로 할당했다면 변수 선언만 호이스팅되고 undefined를 가지므로, 할당 전에 함수로 호출하면 TypeError가 발생합니다.
// sayHi(); // TypeError: sayHi is not a function
var sayHi = function() {
console.log("Hi!");
};
요약 및 정리
호이스팅은 JavaScript 엔진의 코드 처리 방식을 이해하는 데 중요한 개념입니다.
var와 함수 선언문: 선언이 스코프 최상단으로 끌어올려집니다.var는undefined로 초기화, 함수 선언문은 전체가 호이스팅됩니다.let,const: 선언만 호이스팅되며, TDZ로 인해 선언 전에 접근할 수 없어 코드의 안정성을 높입니다.- 권장 사항: 호이스팅으로 인한 혼란을 피하기 위해, 항상 스코프의 시작 부분에서 변수와 함수를 선언하는 습관을 들이는 것이 좋습니다. 또한,
var대신let과const를 사용하면 TDZ 덕분에 잠재적인 버그를 쉽게 발견할 수 있습니다.