호이스팅(Hoisting)
호이스팅은 선언문이 스코프 내부의 가장 최상단으로 끌어 올려지는 것을 의미합니다.
1
2
3
4
5
6
7
8
9
10
11
// 1.
console.log(a); // Undefined
var a = 1;
// 위 코드는 호이스팅으로 인해 아래처럼 동작합니다.
// 2.
var a;
console.log(a);
a = 1;
여기서 중요한건 1번 코드에서 변수 a
선언 전에 a
를 호출 햇지만 에러가 나오지 않고 값이 없다(Undefined)고 나옵니다. 1번 코드는 호이스팅이 발생하여 2번 코드 처럼 처리됩니다.
호이스팅(let 과 const)
let
과 const
키워드로 선언된 변수는 var
키워드로 선언된 변수와는 다르게 선언과 초기화가 분리되어 있습니다, 선언 단계는 스코프 최상단으로 끌어올려져 실행되지만 초기화 단계는 선언문을 만나야 사용할 수 있습니다. 그리고 초기화 전에 변수를 호출한다면 ReferenceError
가 발생합니다, 선언 단계는 스코프 최상단부터 초기화 단계를 실행하는 선언문을 만나기 전까지 변수에 접근할 수 없으며 이 구간을 TDZ( Temporal Dead Zone)
라고 부릅니다.
let과 const의 변수 생성 과정과 TDZ
그림을 보면 위에서부터 선언 > TDZ > 초기화 > 할당
순으로 되어있는데, let
과 const
키워드로 변수를 선언하면 호이스팅이 발생해 선언한 스코프 최상단에서 변수 선언이 이루어지고 초기화 단계까지 TDZ
입니다 초기화랑 할당 단계는 변수 선언문을 만나야 실행이 됩니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// 1.
let a = 1;
function foo(){
console.log(a); // ReferenceError
let a = 2;
}
// 2.
let a = 1;
function foo(){
//변수 a는 변수를 선언한 함수 foo스코프 최상단으로 끌어 올려져 선언 단계가 시작됩니다.
//let a // 여기서부터 변수 선언문을 만나기 전까지 TDZ입니다.
console.log(a); // TDZ 안에서 변수 a를 호출할수 없으니 에러가 발생합니다.
let a = 2; // 여기선 초기화, 할당 단계가 이루어지며 여기서부터 변수 a에 접근할수 있습니다.
}
함수 선언문의 호이스팅
함수 선언문 역시 선언문이기 때문에 호이스팅이 발생하며 함수의 선언, 초기화, 할당
이 세 가지 단계가 한 번에 이루어지기 때문에 아래 코드처럼 동작합니다.
1
2
3
4
5
6
console.log(foo()) // 1
function foo(){
console.log(1)
}
복습
let
과 const
키워드로 선언한 변수의 초기화는 선언문을 만나는 시점에 실행되지만 선언 단계는 스코프 최상단으로 끌어올려져서 실행됩니다.
1
2
3
4
5
6
let a = 1;
function foo(){
console.log(a); // 1 이 출력될것 같지만 ReferenceError 발생
let a = 2;
}
let
과 const
는 선언과 초기화 단계가 분리되어 있고 선언 단계는 스코프 최상단으로 끌어올려지기 때문에 함수 foo
스코프에서 console.log(a)
바로 윗줄에 let a
가 선언이 되며 console.log(a)
바로 밑줄인 let a = 2(선언문)
선언문을 만나기 전까지 TDZ
이며 let a = 2
부터 TDZ
단계가 끝나며 a
변수를 호출할 수 있습니다.
함수 선언문은 선언, 초기화, 할당
이 한 번에 이루어지고 선언문이기 때문에 호이스팅이 발생합니다.