자바스크립트는 변수가 선언 될 때 호이스팅이 발생해 스코프의 가장 위로 올라가게 된다. 그리고 많은 사람들이 let, const는 호이스팅이 일어나지 않는다고 알고 있지만 사실과는 약간 다르다. TDZ의 개념과 함께 정리해보자.
A var statement declares variables that are scoped to the running execution context’s VariableEnvironment. Var variables are created when their containing Lexical Environment is instantiated and are initialized to undefined when created.
- Variable statement
위에서 정의된 var 키워드의 정의를 보면 , var 키워드를 가진 변수들은 Lexical Environment가 초기화 될 때 만들어지게 되고, 그 순간 undefied로 초기화 된다고 한다.
Lexical Environment가 초기화 될 때 만들어지게 되고
이 부분을 사실상 호이스팅으로 봐도 무방할 것이다.
let and const declarations define variables that are scoped to the running execution context’s LexicalEnvironment. The variables are created when their containing Lexical Environment is instantiated but may not be accessed in any way until the variable’s LexicalBinding is evaluated. A variable defined by a LexicalBinding with an Initializer is assigned the value of its Initializer’s AssignmentExpression when the LexicalBinding is evaluated, not when the variable is created.
- let and const declarations
위에 정의된 let과 const를 살펴보면, let과 const의 경우 var와 같이 Lexical Environment가 초기화 될 때 만들어지지만(즉, 호이스팅은 발생하지만) 접근은 불가하다고 설명되어진다.
여기서 TDZ(Temporal Dead Zone)의 개념이 등장한다.
TDZ는 간단히 말해, LexicalBinding이 이뤄지기 전에 접근 불가한 구역이며 let, const , class, 매개변수 등에 적용 된다.
코드로 예를 들면
let a = 1;
{
console.log(a); // ReferenceError
let a = 2;
}
다음의 코드에서 호이스팅이 일어나지 않는다면, 1이 로그에 찍혀야 할 것이다.
하지만 새로운 block scope에 들어가면서 다시 호이스팅이 발생했고, block안의 a는 2로 초기화 되는 구문이 실행되기 전 까지 TDZ에 들어가게 된다. TDZ내에 있는 a를 참조하려고 시도하다 Error가 발생한 경우다.
Resource
https://tc39.es/ecma262/#sec-variable-statement
https://tc39.es/ecma262/#sec-let-and-const-declarations
https://ui.toast.com/weekly-pick/ko_20191014/
https://2ality.com/2015/10/why-tdz.html