호이스팅은 일부 타입의 변수를 실제로 선언되기 전에 코드 내에서 접근 또는 사용가능하게 하는 것을 의미한다.
표면상으로는 특정 변수를 해당 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/