변수와 함수 선언을 컴파일 단계에서 각각의 스코프의 맨 위로 이동시키는 매커니즘으로, 이동한 정보들이 실행 전의 상태에 있을 때를 호이스팅이라고 한다. 변수나 함수가 해당 스코프 내의 어느 곳에서 선언되었는지와 상관 없이 그 스코프 내에서 어디서든지 접근 가능하다.
변수는 실행 컨텍스트에 의해 생성된다. 함수나 블록 내에서 변수 선언시 해당 변수는 컨텍스트 내부에서 생성되며, 해당 변수가 속한 스코프에 대한 정보가 유지된다. 하지만 변수가 선언되기도 전에 참조된다면 해당 변수는 스코프에 존재하지 않는 상태로 실행 컨텍스트가 생성되기 때문에 ReferenceError가 발생한다. 이를 방지하기 위해 코드 실행 전 변수 선언을 미리 처리해주는 것이다.
var a = 7;
자바스크립트는 위 변수 선언을 두 개의 구문, 즉 var a
와 a = 7
로 취급한다. 전자는 컴파일러 단계에서, 후자는 실행 단계에서 처리한다. 다시 말해 스코프의 선언문은 코드가 실행되기 전에 먼저 처리된다.
let
,const
에서는 호이스팅이 발생하나 적용되지 않고var
에서만 적용된다.
function a (x) {
console.log(x); // 1
var x;
console.log(x) // undefined
var x = 2;
console.log(x); // 2
}
a(1);
호이스팅 적용 전
1. a(1) ➡️ x = 1 ➡️ console.log(x) = 1
2. var x; ➡️ console.log(x) = undefined
3. var x = 2; ➡️ console.log(x) = 2
호이스팅 적용 후
1.var x
2.var x
3.var x
4.a(1) ➡️ x = 1
5.console.log(x) = 1
6.console.log(x) = 1
7.x = 2;
8.console.log(x) = 2
함수 선언식
함수 자체가 호이스팅 되기 때문에 기존의 코드에 영향이 갈 수 있으므로 주의 필요
ex) function a () {...}
➡️ 전체 호이스팅
함수 표현식
변수만 호이스팅
var example = function a() {...}
➡️ var example
만 호이스팅
let
,const
로 선언된 변수 사용을 비허용하는 공간.let
,const
역시var
와 마찬가지로 블록의 맨 위로 호이스팅되지만, 초기화되지 않은 상태로 TDZ에 남아있다. 그렇기 때문에 변수에 접근하면 ReferenceError가 발생한다.
var
에도 TDZ 개념이 없는 것은 아니나 TDZ가 적용되는 범위가 좁다. 변수 선언과 할당이 동시에 이루어지지 않더라도 호이스팅에 의해 변수가 함수 혹은 전역 스코프에 속한 것으로 간주되기 때문이다.
반면에 let
과 const
는 보다 엄격한 규칙이 적용된다. 이 둘은 블록 레벨 스코프를 따르는데, 블록 스코프 내에서 변수의 선언과 초기화는 분리되어 있다. 그렇기 때문에 해당 블록 내에서 변수가 선언되기 전까지는 사용할 수 없는 것이다. var
에 비해 엄격하지만 이러한 동작 방식 덕분에 예상치 못한 결과를 방지할 수 있다.