Hoisting
- 변수나 함수가 해당 스코프의 최상단으로 끌어올려진 것 같은 현상
-> 동일한 스코프 내에서는 어디서든지 참조할 수 있다는 것을 말함
scope에 대한 사전지식
- scope : 변수에 접근할 수 있는 범위
-> var로 선언한 변수와 let 또는 const로 선언한 변수의 스코프는 다름
- 블록 스코프 -> 중괄호 {}로 감싸진 범위
- 함수 스코프 -> function(){}에서 중괄호 {} 내부의 범위
-> 즉 함수 코드 블록 내부의 범위
- 자바스크립트는 기본적으로 함수 스코프를 따름
-> var로 변수를 생성할 시 함수 스코프 내에서 유효함
-> but let, const로 변수를 생성할 시, 블록 스코프 내에서 유효함
호이스팅이 왜 일어날까?
- 자바스크립트 변수생성과 초기화(선언과 할당)가 분리되어 진행되기 때문
JavaScript에 대한 사전지식
- 자바스크립트 함수는 실행되기 전에 함수 안에 필요한 변수값들을 모두 모아서 유효 범위의 최상단에 선언함
- 자바스크립트 Parser가 함수 실행 전 해당 함수를 한 번 훑음
- 함수 안에 존재하는 변수/함수 선언에 대한 정보를 기억하고 있다가 실행시킴
- 유효 범위 -> 함수 블록 { } 안에서 유효
-> 즉, 함수 내에서 아래쪽에 존재하는 내용 중 필요한 값들을 끌어올리는 것
-> 실제로 코드가 끌어올려지는 건 아니며, 자바스크립트 Parser 내부적으로 끌어올려서 처리하는 것임
-> 따라서 실제 메모리에서는 변화가 없음
왜 var를 쓰면 안좋을까?
- var로 선언된 변수는 함수 스코프를 가짐
-> hoisting(호이스팅) 발생
-> 예상치 못한 동작 발생할 수 있음
function example() {
console.log(x);
var x = 17;
}
변수는 어떻게 생성되고, 호이스팅은 어떻게 이뤄질까?
1단계: 선언 단계(Declaration phase)
- 변수를 실행 컨텍스트의 변수 객체에 등록
-> 이 변수 객체는 스코프가 참조하는 대상이 됨
2단계: 초기화 단계(Initialization phase)
- 변수 객체에 등록된 변수를 위한 공간을 메모리에 확보함
-> 이 단계에서 변수는 undefined로 초기화됨
3단계: 할당 단계(Assignment phase)
- undefined로 초기화된 변수에 실제 값을 할당됨
- let, const를 사용해 변수를 생성할 시에는 3 단계가 각각 따로따로 이뤄짐
- var 을 사용해 변수를 생성할 시에는 선언 단계와 초기화 단계가 한번에 이뤄짐
- 함수 선언문을 사용할 시에는 세 단계가 한 번에 이뤄짐
-> 선언, 초기화, 할당이 한 번에 이뤄짐
-> 함수 전체가 스코프 최상단으로 호이스팅
TDZ
- let, const을 사용하여 변수를 선언하였을 때, 해당 변수를 선언하기 이전에는 접근할 수 없는 구간을 의미함
-> TDZ는 변수가 선언되기 전까지 변수를 사용하려 할 때 ReferenceError가 발생하게 됨 (어떠한 값도 가지지 않기 때문에)
-> 즉, 변수가 선언되기 이전에는 접근할 수 없고,
변수가 초기화된 이후에 사용할 수 있음
TDZ가 왜 필요한가?
- Temporal Dead Zone은 변수의 스코프를 명확하게 하기 위한 것
-> 이전에는 var 키워드를 사용하여 변수를 선언하면, 변수가 선언되기 이전에도 해당 변수에 접근할 수 있었으며, 값이 undefined로 할당되었음
-> 이는 예기치 못한 동작을 일으킬 수 있는 위험이 있음
-> 따라서 let과 const를 사용하여 변수를 선언하면, 변수가 선언되기 이전에는 해당 변수에 접근할 수 없으며, TDZ에 진입하게 됨
-> 이렇게 함으로써 변수의 스코프를 더욱 명확하게 하고, 예기치 못한 동작을 방지할 수 있음