본문 바로가기
JavaScript

[JavaScript] 스코프와 호이스팅 그리고 TDZ (Scope, Hoisting, Temporal Dead Zone)

by 밀가루빵가루 2022. 2. 16.
728x90

스코프랑 호이스팅은 대략적으로 알고 있다고 생각했는데

1년 전에 잠시 스쳐 지나갔던 TDZ는 오랜만에 보니 또 새롭다.

 

스코프


  • 자바스크립트의 스코프는 함수 레벨 스코프를 따른다.
  • 같은 함수 레벨에 존재하면 값을 참조할 수 있다는 건데
  • ES6에서 let 키워드가 도입되면서 블록 레벨 스코프를 사용할 수 있게 됐다.

 

전역 스코프

- 어디서든 참조 가능

전역 변수

- 전역 스코프를 갖는 전역 변수

- 어디서든 참조 가능

 

지역 스코프

- 함수 자신과 하위 함수에서만 참조 가능

지역 변수

- 지역 스코프를 갖는 지역 변수

- 함수 내에서 선언된 변수로 해당 함수와 해당 함수의 하위 함수에서 참조 가능

 

암묵적 전역 변수

- 선언하지 않은 변수에 값을 할당하면 전역 객체의 프로퍼티가 되어 전역 변수처럼 동작한다.

- 하지만 변수 선언이 없었기 때문에 호이스팅은 발생하지 않는다.

(variable = 1) === (window.variable = 1)

//////////////////////////////////////

console.log('test', test);

function temp () {
  test = 10;
};

temp(); // test is not defined

 

 

 

 

호이스팅


  • 함수의 코드를 실행하기 전에 변수와 함수의 메모리 공간을 선언 전에 미리 할당하는 것.
  • 초기화를 제외한 선언만 호이스팅.
  • 그렇기 때문에 선언, 정의된 코드보다 호출하는 코드를 먼저 배치할 수 있음.
  • 변수의 선언과 초기화를 분리.
  • 변수의 선언을 코드의 최상단으로 끌어올림.
catName("조미료");

function catName(name) {
  console.log("제 고양이의 이름은 " + name + "입니다");
}

// "제 고양이의 이름은 조미료 입니다"

 

변수 선언 형식에 따른 초기화

var : 호이스팅 시 undefined로 변수를 초기화

function : 선언된 위치와 상관없이 동일하게 호출

let, const : 호이스팅 시 변수를 초기화하지 않음. (호이스팅 대상은 맞음)

console.log(num); // 호이스팅한 var 선언으로 인해 undefined 출력
var num; // 선언
num = 6; // 초기화

console.log(num2); // ReferenceError: num2 is not defined
let num2 = 2;

//-----------------------------------------------

catName("조미료"); // "제 고양이의 이름은 조미료 입니다"

function catName(name) {
  console.log("제 고양이의 이름은 " + name + "입니다");
}

catName("조미료"); // "제 고양이의 이름은 조미료 입니다"

 

TDZ(Temporal Dead Zone, 일시적 사각지대)

- TDZ의 영항을 받는 구문 const, let, class

- 변수 스코프의 맨 위에서부터 ~ 변수의 초기화 완료 시점까지의 변수는 TDZ에 들어간 변수

- 코드의 작성 순서(위치)가 아니라 코드의 실행 순서(시간)에 의해 형성

 

let, const

{
    // <----- TDZ가 스코프 맨 위에서부터 시작
    const func = () => console.log(letVar); // OK

    // TDZ 안에서 letVar에 접근하면 ReferenceError

    let letVar = 3; // letVar의 TDZ 종료 ------->

    func(); // TDZ 밖에서 호출함
}

- let 변수 선언 코드가 그 변수에 접근하는 함수보다 아래에 위치하지만 함수의 호출 시점이 사각지대 밖이므로
정상 동작.

 

class

- 부모 클래스를 상속받을 경우, 생성자 안에서 super()호출을 하기 전까지 this바인딩은 TDZ안에 있다.

// (X)
class User extends Member {
  constructor(phone) {
    this.phone = phone;
    super(phone);
  }
}

// (O)
class User extends Member {
  constructor(phone) {
    super(phone);
    this.phone = phone;
  }
}

 

 

결론

- TDZ는 선언 전에 변수를 사용하는 것을 허용하지 않는다.

- var의 사용은 의도치 않은 중복선언과 재할당으로 문제가 생길 수 있기 때문에 사용하지 않는편이 좋다.

 

 

 

 

 

참조

https://developer.mozilla.org/ko/docs/Glossary/Hoisting

 

호이스팅 - 용어 사전 | MDN

JavaScript에서 호이스팅(hoisting)이란, 인터프리터가 변수와 함수의 메모리 공간을 선언 전에 미리 할당하는 것을 의미합니다. var로 선언한 변수의 경우 호이스팅 시 undefined로 변수를 초기화합니다

developer.mozilla.org

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

 

TDZ을 모른 채 자바스크립트 변수를 사용하지 말라

간단한 질문을 하나 하겠다. 아래 코드 스니펫에서 에러가 발생할까? 첫 번째 코드는 인스턴스를 생성한 다음 클래스를 선언한다.

ui.toast.com

 

반응형

댓글