호이스팅(Hoisting) 이란?
자바스크립트에서 호이스팅(Hoisting)은 변수 선언과 함수 선언을 코드의 맨 위로 끌어올려지는 현상을 일컫는다.
호이스팅은 ECMAScript 사양에서 규범적으로 정의된 용어가 아닙니다.
호이스팅 간주하는 경우
1. 변수가 선언된 줄 이전에 해당 범위에서 변수 값을 사용할 수 있는 경우
⭐️Point
: 범위 안에서 변수가 존재하는 사실 자체가 미리 적용
console.log(a); // undefined → 값 호이스팅
var a = 10;
console.log(a); // 10
2. 변수가 선언된 줄 이전에 해당 범위의 변수를 참조할 수 있지만 ReferenceError를 던지지 않고 값이 항상 정의되지 않을 경우
- var는 선언은 끌어올려짐, 값은 끌어올려지지 않음 → 선언 이전 접근 가능하지만 값은 undefined
- let / const는 선언만 끌어올려지고 초기화 전 접근 시 ReferenceError 발생(TDZ)
⭐️Point
: 선언 이전 접근 가능 여부와 TDZ 차이
console.log(a) // undefined
var a = 10;
console.log(a) // 10
console.log(b); // ReferenceError → let/const는 TDZ 존재
console.log(c); // ReferenceError → let/const는 TDZ 존재
let b = 20;
const c = 30;
console.log(b); // 20
console.log(c) // 30
TDZ (Temporal Dead Zone)? TDZ는 변수가 실제로 선언되기 전까지 접근할 수 없는 영역을 의미합니다.
3. 변수를 선언하면 변수가 선언된 줄 앞의 범위에서 동작이 변경됩니다.
⭐️Point
: 선언 이전에 값을 읽을 수 있는 현상, ReferenceError는 발생하지 않음
console.log(msg); // undefined → 선언이 호이스팅됨
var msg = "Hello, world!";
console.log(msg); // "Hello, world!"
console.log(1)
4. 선언의 부작용은 선언이 포함된 나머지 코드를 평가하기 전에 발생합니다.
⭐️Point
: 선언이 코드 평가 전에 끌어올려져 나머지 코드에 영향
console.log(y); // undefined
y = 5; // 실제 할당
var y; // 선언이 코드 평가 전에 끌어올려짐
console.log(y); // 5
자바스크립트에서의 변수 처리 단계
- 선언 단계 (Declaration phase) : 변수를 실행 컨텍스트의 변수 객체에 등록
- 초기화 단계 (Initialization phase) : 변수 객체에 등록된 변수를 위한 공간을 메모리에 확보
- 할당 단계 (Assignment phase) : undefined로 초기화된 변수에 실제 값 할당단계는 여러가지가 있다
📌 호이스팅 발생 원인
자바스크립트의 변수 생성(Instantiation)과 초기화(Initialization)의 작업이 분리돼서 진행되기 때문이다.
함수 선언식 or 함수 표현식
// 함수 선언식
function add(x, y) {
return x + y;
}
// 함수 표현식
const add = function(x, y) {
return x + y;
};
자바스크립트에서 함수 표현식은 함수 선언식보다 더 유연합니다. 표현식은 변수를 통해 함수를 동적으로 할당하거나, 콜백 함수와 같이 특정 상황에서만 실행되도록 쉽게 사용할 수 있기 때문입니다.
하지만 디버깅
측면에서는 표현식이 항상 유리한 것은 아닙니다. 함수 선언식은 항상 이름이 붙어 있어서 디버깅할 때 호출 스택에서 식별하기가 더 쉽습니다.
함수의 호이스팅
1console.log('위 : ' + add(2, 3)); // 호이스팅 발생❗️
2
3function add(x, y) {
4 return x + y;
5}
6
7console.log('아래 : ' + add(3, 4));
함수 선언식은 정의 전체가 호이스팅되기 때문에, 함수가 코드 아래에 작성되어 있어도
선언 이전부터 정상적으로 호출할 수 있습니다.
1console.log(add(2, 3)); // "Error: add is not a function"
2
3// 함수 표현식 형태로 add() 함수 정의
4var add = function (x, y) {
5return x + y;
6
7}
8
9console.log(add(3, 4)); // 7
이 경우 add 자체는 호이스팅 때문에 undefined로 초기화되어 있습니다.
그래서 실행 시,
- 자바스크립트는 add(2, 3)을 평가하려고 시도함
- 그런데 add의 값이 undefined
- 따라서 “TypeError: add is not a function” 이 발생합니다.
📚 내용 요약
구분 | 호이스팅 여부 | 초기화 시점 | 선언 전 접근 시 | 특징 |
---|---|---|---|---|
var | ✅ 됨 | undefined 초기화 | undefined 반환 | 함수 스코프, 선언 전 접근 가능 |
let | ✅ 됨 | 선언문 도달 시 초기화 | ❌ ReferenceError (TDZ) | 블록 스코프, 안전함 |
const | ✅ 됨 | 선언문 도달 시 초기화 | ❌ ReferenceError (TDZ) | 블록 스코프, 재할당 불가 |
함수 선언식 | ✅ 됨 (정의 전체) | 코드 실행 전 초기화 | 정상 호출 가능 | 선언 전에 호출 가능 |
함수 표현식 (var ) | 변수만 호이스팅 | 런타임 할당 시 | undefined → TypeError 발생 | 선언 전 호출 불가 |
함수 표현식 (let/const ) | 변수만 호이스팅 | 선언문 도달 시 초기화 | ❌ ReferenceError (TDZ) | 선언 전 호출 불가 |
📌 호이스팅은 변수와 함수 선언이 실행 컨텍스트 생성 시점에 메모리에 미리 등록되기 때문에 발생하는 현상입니다.
- var는 선언과 동시에 undefined로 초기화되어 선언 전에도 접근 가능하지만, 의도치 않은 버그를 유발할 수 있습니다.
- let과 const는 TDZ 때문에 선언 이전에는 사용할 수 없어 더 안전합니다.
- 함수 선언식은 전체가 호이스팅되므로 선언 전에 호출 가능하지만, 함수 표현식은 변수의 호이스팅 방식에 따라 동작이 달라집니다.
따라서 실무에서는 var 대신 let/const, 필요에 따라 함수 표현식을 활용하는 것이 일반적입니다.
🤔 그래서 결론은?
호이스팅은 코드가 위로 올라간 것처럼 보이게 만드는 자바스크립트의 내부 처리 방식으로, 선언 이전에도 존재를 인지하게 하지만 접근 방식에 따라 결과가 달라집니다. 따라서 이를 이해하고 주의하며 사용해야 합니다❗️
- https://inpa.tistory.com/entry/JS-📚-스코프-함수-호이스팅 [Inpa Dev 👨💻:티스토리]
- https://ko.javascript.info/var [모던 Javascript 튜토리얼]
- https://developer.mozilla.org/ko/docs/Glossary/Hoisting [MDN]