
호이스팅은 일부 타입의 변수를 실제로 선언되기 전에 코드 내에서 접근 또는 사용가능하게 하는 것을 의미한다.
표면상으로는 특정 변수를 해당 scope의 꼭대기로 올리는 것처럼 보이지만 실제 동작 원리는 다음과 같다.
자바스크립트 엔진은 코드를 실행하기 전에 변수 선언을 스캔하는데,
이 작업은 execution context의 creation phase에서 이루어지며,
이 단계에서 코드 내에 선언된 모든 변수와 함수가 variable environment object에 저장된다.
execution context and call stack 포스팅
호이스팅은 모든 변수 타입에 똑같이 작동하지 않는다.
여기서 말하는 변수에는 함수도 포함된다.
하지만 함수 선언식은 제외한다. 함수를 변수에 저장하는 것이 아니기 때문이다.
따라서 함수를 선언전에 사용하고 싶으면 함수 선언식을 사용하면 되고, 이를 제외한 함수 표현식과 화살표 함수의 호이스팅 여부는 변수 선언 키워드에 따라 달라진다.
var로 선언된 변수는 호이스팅되기는 하지만 초기값은 undefined이다.var를 거의 안쓰는 주된 이유 중 하나이다.let과 const는 호이스팅되지 않는다.
TDZ는 해당 변수의 scope 시작부분과 해당 변수 선언 라인 사이의 공간을 의미한다.
자바스크립트 엔진은 코드를 실행하기 전에 이미 코드를 읽었기 때문에 job 변수가 초기화될 것이라는 것을 이미 알고 있다.
그래서 const로 선언된 job변수를 variable environment에 uninitialized 상태로 설정해놓았다.
코드가 실행되고 변수가 선언된 라인에 도달하면 TDZ에서 벗어나job변수를 사용할 수 있게 된다.
즉 엔진은 이미 job 변수의 존재를 알고 있지만 변수 선언 라인(초기화) 이후 즉 TDZ 이후에 접근할 수 있다고 알려준다.
에러 메시지를 통해 기술적으로는 호이스팅되었지만 사용은 불가능하다 라는 말을 이해할 수 있다.
변수 x처럼 아예 선언이 되지 않았다면 ReferenceError: x is not defined라는 에러가 발생하지만,
const로 선언된 변수가 아직 TDZ에 있는데 사용하려 하면 ReferenceError: Cannot access 'job' before initialization이라는 에러가 발생한다.
요약하면 다음과 같다.
let이나const로 선언된 모든 변수는 scope의 시작부터 변수 선언 라인까지의 TDZ를 갖는다.
그렇게 선언된 변수는 TDZ 이후에만 안전하게 사용가능하다.
TDZ는 let, const와 함께 ES6에서 등장한 개념이다.
그렇다면 왜 등장하게 되었을까.
const로 선언된 변수가 제대로 동작하게 하기 위함이다.var 키워드로 선언된 변수는 선언 전에 undefined로 초기화가 되고 나중에 진짜 value를 할당된다.const 변수는 재할당이 불가능하기 때문에 이러한 동작 자체가 불가능하다.var 키워드 사용하지 말 것.const 사용하고, 필요시 let 쓸 것.https://developer.mozilla.org/en-US/docs/Glossary/Hoisting
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/let#temporal_dead_zone_tdz
https://www.udemy.com/course/the-complete-javascript-course/