Front-End/Javascript

let과 const는 호이스팅되지 않는다?? TDZ란

태나미 2021. 8. 28. 20:47
지난 시간에 var, let, const를 비교하면서 공부를 하였는데,
이번 시간에는 TDZ란 무엇이고, 추가적으로 공부를 하기 위해서 작성하였습니다

1. TDZ란?

TDZ란 변수가 선언되고 초기화되기의 범위를 TDZ(Temporal Dead Zone)에 있다고 합니다.

var, let, const를 보면서 TDZ에 대해 배워보겠습니다.

2. var와 let, const 비교

1) var

console.log(myName); // undefined

var myName = "taenami";

var는 선언하기 전에 사용할 수 있습니다.

위와 같이 선언한 myName이라는 변수는 error가 발생하는 대신, undefined가 나오는데, var로 선언된 변수는 *호이스팅 되기 때문입니다.

 

2) let, const

console.log(myName); // ReferenceError

let myName = "taenami";
console.log(myName); // ReferenceError

const myName = "taenami";

let과 const로 선언된 변수은 선언하기 전에 사용할 수 없습니다.

위와 같은 에러가 발생한다고 해서, 호이스팅 되지 않는 것이 아닙니다.

let과 const로 선언된 변수는 TDZ (Temporal Dead Zone)에 영향을 받기 때문인데, TDZ에 있는 변수들은 사용할 수 없습니다. TDZ에 대해서 알아보기 위해 다음으로 변수의 생성과정을 보면서 이해해보겠습니다.

3. 변수 생성 3단계

javascript에서 변수는 3가지 단계의 생성과정을 걸쳐 생성됩니다.

1. 선언 단계

2. 초기화 단계

3. 할당 단계

 

선언 단계(Declaration phase): 변수를 *실행 컨텍스트의 변수 객체에 등록하는 단계를 의미합니다. 이 변수 객체는 *스코프가 참조하는 대상이 됩니다.

초기화 단계(Initialization phase) : 실행 컨텍스트에 존재하는 변수 객체에 선언 단계의 변수를 위한 메모리를 만드는 단계입니다. 이 단계에서 할당된 메모리에는 undefined로 초기화됩니다.

할당 단계(Assignment phase) : 사용자가 undefined로 초기화된 메모리의 다른 값을 할당하는 단계입니다. 

 

1)  var 

var 키워드로 선언된 변수는 선언과 초기화가 동시에 진행되는데, 할당하기 전에 호출하면 error가 발생하지 않고 undefined를 반환합니다. 이후 변수 할당 단계에 도달하면 값이 할당됩니다.

var myName;

console.log(myName); // undefined

myName = "taenami";

첫 번째 줄에서, 선언 단계 및 초기화 단계가 동시에 진행되었습니다.

두 번째 줄에서, 선언, 초기화 단계가 진행되었기 때문에, name이라는 변수는 undefined가 나오게 된 것을 볼 수 있고,

마지막 줄에서, myName의 값이 할당됩니다.

 

2)  let 

 

let 키워드로 선언된 변수는 선언 단계와 초기화 단계가 나누어서 진행됩니다.

스코프에 변수를 등록(선언단계)하지만 초기화 단계는 변수 선언문에 도달했을 때 이루어집니다. 그렇기 때문에, 초기화 이전에 변수에 접근하면 참조 에러(Reference Error)가 발생합니다. 

console.log(myName); // Reference Error, TDZ구간

let myName; // 초기화 단계
console.log(myName); // undefined

myName = 'taenami'; // 할당 단계
console.log(myName); // taenami
let age = 10; // 전역 변수

{
  console.log(age); // Reference Error
  let age = 29; // 지역 변수
}

위 예제에서는 let으로 선언한 변수는 호이스팅이 된다는 것을 알려주고 있습니다.

만약 호이스팅이 되지 않았다면 전역변수의 값인 10을 출력이 되었겠지만, 지역 변수 age도 해당 스코프에서 호이스팅 되고, 코드 블록의 시작점부터, 초기화가 이루어지는 지점까지의 TDZ에 빠지게 되어 위와 같은 에러가 발생합니다.

 

3)  const 

const는 재할당 및 재선언이 금지됩니다.

그렇기 때문에, const 키워드로 선언된 변수는 선언 및 할당을 동시에 해야 합니다.

4. 정리

공부하기 이전에는 let과 const가 오류가 나는 점으로 보아, var 키워드로 선언된 변수만 호이스팅이 가능하다고 생각하였습니다.

하지만 let으로 선언된 변수는 호이스팅이 되고, TDZ에 걸리기 때문에, Reference Error가 발생하였습니다.

위에서 const, let으로 선언된 변수의 오류를 바로 잡으려면 아래와 같이 작성하면 정상적으로 값이 출력됩니다.

let myName = "taenami";
const myAge = 29;

console.log(myName); // taenami
console.log(myAge); // 29

 

변수의 선언 시 var의 사용보다 let과 const를 올바르게 사용해야 예측 가능한 결과를 내고 버그를 줄일 수 있다고 생각하였습니다.

 

TDZ의 영향을 받는 구문으로는 다음과 같습니다.

1) const 변수

2) let 변수

3) class 구문

4) constructor() 내부의 super()

5. 기본 함수 매개변수 (default Function Parameter)

 

반대로 TDZ의 영향을 받지 않는 구문으로는 다음과 같습니다.

1) var 변수

2) 함수 선언식

 

* 호이스팅 : 스코프 내부 어디서든 변수 선언은 최상위에 선언된 것처럼 행동

* 실행 컨텍스트 : 코드가 실행되기 위해 필요한 환경

* 스코프 : 변수가 값을 참조할 때 접근할 범위

 

 

출처:

https://www.youtube.com/watch?v=ocGc-AmWSnQ

https://ui.toast.com/weekly-pick/ko_20191014

https://noogoonaa.tistory.com/78

https://leesoo7595.github.io/2019/12/01/JavaScript_js_scope/

https://velog.io/@kihyeon8949/%EB%B3%80%EC%88%98%EC%8A%A4%EC%BD%94%ED%94%84%ED%98%B8%EC%9D%B4%EC%8A%A4%ED%8C%85TDZ

https://poiemaweb.com/es6-block-scope

 

사진출처:

https://velog.io/@kihyeon8949/%EB%B3%80%EC%88%98%EC%8A%A4%EC%BD%94%ED%94%84%ED%98%B8%EC%9D%B4%EC%8A%A4%ED%8C%85TDZ