TIL - 호이스팅과 TDZ는 무엇일까?

BUMSU·2022년 8월 5일
0

TIL - Today I Learned

목록 보기
3/25
post-thumbnail

📕 호이스팅과 TDZ는 무엇일까?

  • 스코프, 호이스팅, TDZ

📖 스코프(Scope, 유효범위)

let x = 'global';

function foo () {
  let x = 'function scope';
  console.log(x);
}

foo(); // ?
console.log(x); // ?
  • 참조 대상 식별자(identifier, 변수, 함수의 이름과 같이 어떤 대상을 다른 대상과 구분하여 식별할 수 있는 유일한 이름)를 찾아내기 위한 규칙이다. 자바스크립트는 이 규칙대로 식별자를 찾는다.

  • 프로그래밍은 변수를 선언하고 값을 할당하며 변수를 참조하는 기본적인 기능을 제공하며 이것으로
    프로그램의 상태를 관리할 수 있다. 변수는 전역 또는 코드 블록(if, for, while, try/catch 등)이나 함수 내에 선언하며 코드 블록이나 함수는 중첩될 수 있다. 식별자는 자신이 어디에서 선언됐는지에 의해 자신이 유효한(다른 코드가 자신을 참조할 수 있는) 범위를 갖는다.

  • 위 예제에서 전역에 선언된 변수 x는 어디에든 참조할 수 있다. 하지만 함수 foo 내에서 선언된 변수 x는 함수 foo 내부에서만 참조할 수 있고 함수 외부에서는 참조할 수 없다. 이러한 규칙을 스코프라고 한다.

  • 만약 스코프가 없다면 어떻게 될까? 스코프가 없다면 같은 식별자 이름은 충돌을 일으키므로 프로그램 전체에서 하나밖에 사용할 수 없다. 디렉터리가 없는 컴퓨터를 생각해보자. 디렉터리가 없다면 같은 이름을 갖는 파일을 하나밖에 만들 수 없다. 스코프도 이와 같이 식별자 이름의 충돌을 방지한다.




📖 스코프의 구분

자바스크립트에서 스코프를 구분해보면 다음과 같이 2가지로 나눌 수 있다.


📌 전역 스코프 (Global scope)

  • 코드 어디에서든지 참조할 수 있다.

📌지역 스코프(Local scope or Function-level scope)

  • 함수 코드 블록이 만든 스코프로 함수 자신과 하위 함수에서만 참조할 수 있다.



  • 모든 변수는 스코프를 갖는다.

변수의 관점에서 스코프를 구분하면 다음과 같이 2가지로 나눌 수 있다.


📌 전역 변수 (Global variable)

  • 전역에서 선언된 변수이며 어디에든 참조할 수 있다.

📌 지역 변수 (Local variable)

  • 지역(함수) 내에서 선언된 변수이며 그 지역과 그 지역의 하부 지역에서만 참조할 수 있다.

  • 변수는 선언 위치(전역 또는 지역)에 의해 스코프를 가지게 된다. 즉, 전역에서 선언된 변수는 전역 스코프를 갖는 전역 변수이고, 지역(자바스크립트의 경우 함수 내부)에서 선언된 변수는 지역 스코프를 갖는 지역 변수가 된다.

  • 전역 스코프를 갖는 전역 변수는 전역(코드 어디서든지)에서 참조할 수 있다. 지역(함수 내부)에서 선언된 지역 변수는 그 지역과 그 지역의 하부 지역에서만 참조할 수 있다.




📖 자바스크립트 스코프의 특징

  • 자바스크립트 스코프는 타 언어와는 다른 특징을 가지고 있다.

  • 대부분의 C-family language는 블록 레벨 스코프(block-level scope)를 따른다.

  • 블록 레벨 스코프란 코드 블록({...})내에서 유효한 스코프를 의미한다.

  • 여기서 "유효하다"라는 것은 "참조(접근)할 수 있다"라는 뜻이다.


📌 호이스팅

  • 자바스크립트는 ES6에서 도입된 let, const를 포함하여 모든 선언(var, let, const, function, function*, class)을 호이스팅한다.

  • 호이스팅(Hoisting)이란, var 선언문이나 function 선언문 등을 해당 스코프의 선두로 옮긴 것처럼 동장하는 특성을 말한다.

  • 하지만 var 키워드로 선언된 변수와는 달리 let 키워드로 선언된 변수를 선언문 이전에 참조하면 참조에러(ReferenceError)가 발생한다. 이는 let 키워드로 선언된 변수는 스코프의 시작에서 변수의 선언까지 일시적 사각지대(Temporal Dead Zone; TDZ)에 빠지기 때문이다.

console.log(foo); // undefined
var foo;

console.log(bar); // Error: Uncaught ReferenceError: bar is not defined
let bar;

📌 선언 단계(Declaration phase)

  • 변수를 실행 컨텍스트의 변수 객체(Variable Object)에 등록한다.

  • 이 변수 객체는 스코프가 참조하는 대상이 된다.


📌 초기화 단계(Initialization phase)

  • 변수 객체(Variable Object)에 등록된 변수를 위한 공간을 메모리에 확보한다.

  • 이 단계에서 변수는 undefined로 초기화된다.


📌 할당 단계(Assignment phase)

  • undefined로 초기화된 변수에 실제 값을 할당한다.
  • var 키워드로 선언된 변수는 선언 단계와 초기화 단계가 한번에 이루어진다.

  • 즉, 스코프에 변수를 등록(선언 단계)하고 메모리에 변수를 위한 공간을 확보한 후, undefined로 초기화(초기화 단계)한다. 따라서 변수 선언문 이전에 접근하여도 스코프에 변수가 존재하기 때문에 에러가 발생하지 않는다. 다만 undefined를 반환한다. 이후 변수 할당문에 도달하면 비로소 값이 할당된다.

  • 이러한 현상을 변수 호이스팅(Variable Hoisitng)이라 한다.


// 스코프의 선두에서 선언 단계와 초기화 단계가 실행된다.
// 따라서 변수 선언문 이전에 변수를 참조할 수 있다.
  
console.log(foo); // undefined

var foo;
console.log(foo); // undefined

foo = 1; // 할당문에서 할당 단계가 실행된다.
console.log(foo); // 1

  • let 키워드로 선언된 변수는 선언 단계와 초기화 단계가 분리되어 진행된다.

  • 즉, 스코프에 변수를 등록(선언단계)하지만 초기화 단계는 변수 선언문에 도달했을 때 이루어진다.

  • 초기화 이전에 변수에 접근하려고 하면 참조 어러(ReferenceError)가 발생한다.

  • 이는 변수가 아직 초기화되지 않았기 때문이다. 다시 말하면 변수를 위한 메모리 공간이 아직 확보되지 않았기 떄문이다. 따라서 스코프의 시작 지점부터 초기화 시작 지점까지는 변수를 참조할 수 없다.

  • 스코프의 시작 지점부터 초기화 시작 지점까지의 구간을 '일시적 사각지대 (Temporal Dead zone; TDZ)' 라고 부른다.




실행 컨텍스트와 콜 스택

📌 실행 컨텍스트

  • 실행 컨텍스트(Execution Context)는 scope, hoisting, this, function, closure 등의 동작원리를 담고 있는 자바스크립트의 핵심원리이다.

📌 콜 스택

  • 콜 스택은 여러 함수들을 호출하는 스크립트에서 해당 위치를 추적하는 인터프리터 (웹 브라우저의 자바스크립트 인터프리터같은)를 위한 메커니즘이다. 현재 어떤 함수가 동작하고있는 지, 그 함수 내에서 어떤 함수가 동작하는 지, 다음에 어떤 함수가 호출되어야하는 지 등을 제어한다.

스코프 체인, 변수 은닉화

📌 스코프 체인

  • 스코프 체인(Scope Chain)은 일종의 리스트로서 전역 객체와 중첩된 함수의 스코프의 레퍼런스를 차례로 저장하고 있다. 다시 말해, 스코프 체인은 해당 전역 또는 함수가 참조할 수 있는 변수, 함수 선언 등의 정보를 담고 있는 전역 객체(GO) 또는 활성 객체(AO)의 리스트를 가리킨다.
  • 스코프 체인은 식별자 중에서 객체(전역 객체 제외)의 프로퍼티가 아닌 식별자, 즉 변수를 검색하는 메커니즘이다. n식별자 중에서 변수가 아닌 객체의 프로퍼티(물론 메소드도 포함된다)를 검색하는 메커니즘은 프로토타입 체인(Prototype Chain)이다.

📌 변수 은닉화

  • 캡슐화는 객체의 상태를 나타내는 프로퍼티와 프로퍼티를 참조하고 조작할 수 있는 동작인 메소드를 하나로 묶는 것을 말한다. 캡슐화는 객체의 특정 프로퍼티나 매서드를 감출 목적으로 사용하기도 하는데 이를 정보 은닉이라 한다.




Reference

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

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

     https://poiemaweb.com/js-execution-context

profile
Stay Calm

0개의 댓글