JavaScript 호이스팅과 TDZ (221118) - TIL9

Pablaw·2022년 11월 18일
0

TIL

목록 보기
9/20
post-thumbnail

1. 스코프(scope), 호이스팅(hoisting), TDZ

  • 스코프(scope)

자바스크립트에서의 스코프(scope)는 변수에 접근할 수 있는 범위를 말한다.
식별자를 찾기 위한 규칙이라고 할 수 있다.

<script>
  var x = 'global';

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

  foo(); // function scope
  console.log(x); // global
</script>

위의 경우 전역에 선언된 변수 x는 스크립트 내에서는 어떤 곳이든 참조할 수 있다.
하지만 foo 함수 내 변수 x는 함수 내에서만 참조가 가능하고 외부에서는 참조할 수 없다.

  • 호이스팅(hoisting)

호이스팅(hoisting)은 인터프리터가 변수와 함수의 메모리 공간을 선언 전에 미리 할당하는 것을 말한다.
var로 선언하는 경우 undefined로 변수가 초기화 되고
let이나 const로 선언한 변수의 경우는 변수를 초기화하지 않는다.

<script>
	catName("클로이");

    function catName(name) {
      console.log("제 고양이의 이름은 " + name + "입니다");
    }
    /*
    결과: "제 고양이의 이름은 클로이입니다"
    */
    
</script>

위의 경우 함수의 선언보다 먼저 호출되었지만 정상적으로 작동한다.
자바스크립트 함수는 실행되기 전에 유효 범위의 최상단에 선언한다.(함수 선언식의 경우)
메모리가 이미 할당되기 때문에 선언 이전에 호출이 가능한 것이다.

단, const, let 호이스팅 대상(TDZ 후술)이지만 undefined로 변수를 초기화 하지않기 때문에
초기화 수행하기 전 작동하고자 할 때 예외가 발생한다.

하지만 함수 선언문과 함수 표현식에서 다르게 동작되기 때문에 주의가 필요하다.
변수로 할당된 함수 표현식은 일반 변수의 스코프 규칙을 그대로 따른다.
차례대로 동작되기때문에 선언문보다 안전하다.

  • TDZ(Temporal Dead Zone)

TDZ(Temporal Dead Zone)는 일시적 사각지대라는 의미로 스코프의 시작지점부터 초기화 시작 지점까지의 구간을 의미한다.

자바스크립트에서의 변수는 선언(declaration phase), 초기화(initialization phase), 할당(assignment phase)의 3가지 단계를 거쳐 생성된다.

var 변수 => 선언, 초기화가 즉시 일어나고 (undefined) 후에 할당이 이뤄진다.
let 변수 => 선언, 초기화, 할당이 각각 구분되어 일어나기 때문에 호이스팅 대상이지만 초기화는 동시에
진행되지 않기 때문에 초기화 지점까지 '일시적 사각지대'가 발생하게 된다.
function 선언식의 경우 3단계를 한번에 진행한다.


2. 함수 선언문과 함수 표현식의 호이스팅 차이

함수 선언문의 경우 일시적 사각지대나 undefined 초기화 없이 선언, 초기화, 할당이 동시에 이뤄지며 생성된다.

<script>
	catName("클로이");

    function catName(name) {
      console.log("제 고양이의 이름은 " + name + "입니다");
    }
    /*
    결과: "제 고양이의 이름은 클로이입니다"
    */
    
</script>

그렇기 때문에 위와 같이 함수의 선언보다 호출이 먼저 이뤄지는 경우에도 정상적으로 작동된다.

반면에 함수 표현식의 경우 함수로서 동작하지만 변수와 같이 생성되기 때문에 일반적인 스코프 규칙을 따른다.

<script>
	catName("클로이");

    const catName = function (name) {
                      console.log("제 고양이의 이름은 " + name + "입니다");
                    }
    /*
    Uncaught ReferenceError: Cannot access 'catName' before initializatio
    */
    
</script>

위의 경우 일반적인 변수의 스코프를 따르기 때문에 초기화가 이뤄지지 않아서 참조 에러가 나온다.


2. 실행 컨텍스트(execution context)와 콜스택(call stack)

실행 컨텍스트(execution context)는 자바스크립트 코드가 실행되고 연산되는 범위를 나타내는 추상적인 개념이다. 작성한 코드들은 모두 실행 컨텍스트 내부에서 실행되고 있는 것이다.

전역 실행 컨텍스트 => 함수 내에 없는 코드는 전역 컨텍스트에서 실행된다.
함수 실행 컨텍스트 => 함수 내의 코드를 실행하는 블럭이다.
eval 실행 컨텍스트 => eval 함수를 실행하는 코드이다.

실행 컨텍스트는 논리적 스택 구조를 지닌다. 실행되는 순서에 따라 콜 스택에 쌓이고 스택 가장 위에 쌓여있는 컨텍스트가 실행되게 된다.

<script>
	var z = 'pablaw';

    function foo () {
      var y = 'is';

      function bar () {
        var x = 'name';
        console.log(x + y + z);
      }
      bar();
    }
    foo(); // nameispablaw
</script>

위의 경우 실행컨텍스트가 차례로 전역 -> 함수 -> 함수 내 함수로 콜스택이 쌓이게 되고 콜스택으로 쌓인 실행은 반대로 함수 내 함수 -> 함수 -> 전역으로 실행된다.


3. 스코프 체인(scope chain), 변수 은닉화(infomation hiding)

  • 스코프 체인(scope chain)

스코프가 어떻게 연결되어 있는지 표현되는 방법이다.

console.dir()를 사용해서 [[Socpes]]속성을 통해서 확인할 수 있고 변수의 가장 가까운 순서로 스코프가 나열되는 것을 확인 할 수 있다.

실행 컨텍스트 내용에서 실행되는 범위의 관계를 나타낸 것이라고 할 수 있다.

  • 변수 은닉화(infomation hiding)

함수 외부에서 내부의 변수를 직접적으로 변경할 수 없도록 클로저(closure) 개념을 사용하여서 함수 내에 프라이빗한 변수를 선언하여 원치 않는 외부의 접근으로부터 변수를 보호하는 방법이다.

기존 자바스크립트에서는 private한 변수를 만들기 별개의 노력이 필요했지만 변수앞에 #을 붙여서 프라이빗 변수를 선언하여 사용할 수 있게 되었다.

<script>
	class Human {
        #age = 10;

        getAge() {
          return this.#age; 
        }
      }

    const person = new Human();

    console.log(person.getAge()); // 10
</script>

접근을 위해서도 #을 붙여야 변수에 접근이 가능하다.

profile
반갑습니다, 프론트엔드 개발자를 꿈꾸고 있습니다 ! https://pablaw.github.io/profileLink/

0개의 댓글