JavaScript/JavaScript

[JavaScript] 호이스팅 & TDZ

프라이D 2022. 4. 12. 22:33

호이스팅

  • 변수/함수 선언 시점 이전에 그것에 접근할 수 있는 것.
  • 선언이 마치 스코프의 상단으로 끌어올려진 것 같은 현상이다.
  • 코드 실행 전, 자바스크립트 엔진이 코드를 스캔하고 코드 내의 변수, 함수 선언에 대한 정보를 실행컨텍스트에 기억한다.
  • 이 때, 선언 TYPE에 따라 기억되는 정보가 달라진다. 따라서 호이스팅 결과도 다르게 나타난다.
TYPE HOISTED? 초기값 스코프
함수 선언문 Actual function 블록(strict mode)
var undefined 함수
let & const TDZ(uninitialized) 블록
함수 표현식/화살표 함수 var, let, const 선언 방식에 영향을 받는다.
  • var 선언방식의 경우 선언과 동시에 초기화되므로, undefined의 값을 가지고 코드가 실행된다.
  • letconst의 경우 선언시점 이전까지 초기화 되지 않기 때문에, 접근할 수 없다. 이런 이유로 호이스팅이 적용되지 않는 것처럼 보일 수 있다.
  • 스코프의 시작점부터 let, const로 선언되기 직전까지 초기화되지 않은 값을 가지는 영역을 TDZ (Temporal Dead Zone) 이라고 한다.

TDZ (Temporal Dead Zone)

  • 코드 실행 전 Creation Phase 단계에서, letconst로 선언된 것이 '있다는 것'은 알고 있는 상태.
  • 하지만, 선언 시점 전까지 초기화 되지 않는다.
console.log(x); //Uncaught ReferenceError: Cannot access 'x' before initialization at...

const x = 1;
  • 위 예제와 같이 선언이 되지 않은 것과는 차이가 있다.
  • TDZ는 에러 방지 및 에러의 발견을 쉽게할 수 있도록 도와주고, ES6에 도입된 const (상수 선언)이 가능하도록 만든다. const의 경우 한 번 선언되면 값을 재할당 할 수 없기 때문에, var처럼 undefinedvalue로 재선언 할 수 없다.

Example

if(!number) deleteCart();

var number = 10;

function deleteCart() {
    console.log('카트가 비었습니다.');
}
  • 위 코드의 실행 결과는 아래와 같다.

실행결과

  • if(!number) 부분은 numberfalsy value 일 경우에만 deleteCart( ) 를 실행하도록 되어있다.
  • 하지만 var 선언방식의 호이스팅으로 인해 number는 선언 이전 시점까지 undefined가 할당되어 있다.
  • 따라서 if 구문의 number가 undefined가 아닌 값이기 때문에 위와 같은 결과가 나오는 것이다.

  • 이러한 상황을 방지하기 위해서는...
    1. 되도록 const를 사용하여 선언하고, 추후 재할당이 필요할 경우에는 let을 사용한다. (var 사용 지양)
    2. 가능하면 스코프 상단에 함수를 포함한 모든 선언을 작성한다. 가독성을 높이고 에러를 줄이는 Clean Code 작성에 도움이 된다.
  • 또한 var로 선언된 변수는 window 전역 객체에 프로퍼티를 생성하지만, letconst는 그렇지 않다는 차이가 있다.

정리

  • 호이스팅은 변수/함수 선언 시점 이전에 해당 스코프 내에서 접근 가능한 현상을 말한다.
  • constlet은 호이스팅이 일어나지 않는 것처럼 보이지만, 선언 시점 이전까지 초기화 되지 않은 것 뿐이다. 이를 TDZ 라고 하며, 이 때는 접근할 수 없다.

참고자료