[JS] 호이스팅(Hoisting)
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에 있는 변수는 초기화 후에야 참조가 가능
- 함수 선언문의 경우, 전체 구현이 호이스팅되어 있기 때문에 선언 전에 호출해도 정상 작동