Home

[JS] 모던 자바스크립트 입문 8장 - 자바스크립트 평가와 실행 과정

modern-javascript

모던 자바스크립트 입문

아소 히로시 지음, 서재원 옮김

길벗

모던 자바스크립트 입문 8.5 프로그램의 평가와 실행 과정을 보고나서 이 부분은 자바스크립트를 공부, 사용함에 있어서 매우 중요하다고 생각 되어서 별도로 정리 하였다. 내가 모르는 부분도 상당하였고 이해가 가지 않은 부분은 다른 사이트도 참조 하였다.


8.5 프로그램의 평가와 실행 과정

  • 실행 가능한 코드(Excutable Code)

    • 자바스크립트 엔진은 실행 가능한 코드를 만나면 그 코드를 평가해서 실행 문맥(Excution Context)를 만든다.
    • 실행 가능한 코드의 유형은 다음과 같다.

      • 전역 코드

        • window 전역 객체 아래 정의된 함수
      • 함수 코드

        • 함수 코드
      • eval 코드

        • eval 함수
        • 렉시컬 환경(Lexical Environment)이 아닌 별도의 동적 환경에서 실행된다.
  • 실행 문맥(Excution Context)

    • 실행 가능한 코드가 실제로 실행되고 관리되는 영역
    • 실행에 필요한 모든 정보를 컴포넌트 여러 개로 나누어 관리한다.

      • 렉시컬 환경(LexicalEnvironment) 컴포넌트
      • 변수 환경(VariableEnvironment) 컴포넌트
      • 디스 바인딩(This Binding) 컴포넌트

        • 함수를 호출한 객체의 참조가 저장되는 곳
        • 이것이 가리키는 값이 실행 문맥의 This가 된다.
      • 렉시컬 환경 컴포넌트와 변수 환경 컴포넌트는 타입이 같고, with문을 사용할 때를 제외하곤 내부 값이 똑같아 같은 취급을 해도 된다.
  • 렉시컬 환경 컴포넌트

    • 자바스크립트 엔진이 자바스크립트 코드를 실행하기 위해 자원을 모아둔 곳
    • 함수 또는 블록의 유효 범위 안에 있는 식별자와 그 결과값이 저장되는 곳
    • 자바스크립트 엔진은 유효 범위안에 있는 식별자와 그 식별자가 가리키는 값을 키와 값 쌍으로 바인드 한다.

      • 환경 레코드(Environment Record)

        • 유효 범위 안에 포함된 식별자를 기록하고 실행하는 영역
        • ECMAScript 3의 변수 객체와 비슷한 역할을 한다.
        • 자바스크립트 엔진은 유효 범위 안의 식별자와 결과값을 바인드해서 환경 레코드에 기록한다.
      • 외부 렉시컬 환경 참조(Outer Lexical Environment Reference) 컴포넌트

        • 자바스크립트는 함수안에 함수를 중첩해서 정의할 수 있다. 따라서 유효 범위 너머의 유효 범위도 검색 할 수 있어야 한다.
        • 함수를 둘러싸고 있는 코드가 속한 렉시컬 환경 컴포넌트의 참조가 저장된다.
        • 중첨된 함수 안에서 바깥 코드의 정의된 변수를 읽거나 사용할 때 외부 렉시컬 환경 참조를 따라 변수를 검색한다.
  • 환경 레코드

    • 레시컬 환경 안의 식별자와 그 식별자가 가리키는 값의 묶음이 실제로 저장되는 영역이다.

      • 선언전 환경 레코드(Declarative Environment Record)

        • 실제로 함수와 변수, catch문의 식별자와 실행 결과거 저장된다.
      • 객체 환경 레코드(Object Environment Record)

        • 실행 문맥 외부에 별도로 저장된 객체의 참조에서 데이터를 읽거나 사용한다.
        • 렉시컬 환경이나 전역 객체처럼 별도로 저장된 데이터는 키와 쌍을 복사하는 것이 아닌, 해당 객체의 참조를 가져와서 객체 환경 레코드의 bindObject라는 프로퍼티에 바인드하여 사용한다.
  • 전역 환경과 전역 객체의 생성

    • 자바스크립트 인터프리터는 시작하자마자 렉시컬 환경 타입의 전역 환경(Global Environment)을 생성한다.

    • 그다음 전역 객체를 생성한 다음 전역 환경의 객체 환경 레코드에 전역 객체의 참조를 대입한다.

      // 전역 환경
      GlobalEnvironment = {
        ObjectEnvironmentRecord: {
          bindObject: window
        },
        OuterLexicalEnvironmentReference: null
      }
      
      // 전역 실행 문맥
      ExcutionContext = {
        LexicalEnvironment: GlobalEnvironment,
        ThisBinding: window
      }
  • 프로그램의 평가와 전역 변수

    • 전역 환경과 전역 객체를 생성한 후에는 자바스크립트 프로그램을 읽어 들인다.
    • 자바스크립트 프로그램을 다 읽어 들인 후 프로그램을 평가하며, 최상위 레벨에 var문으로 작성한 전역 변수는 전역 환경의 환경 레코드의 프로퍼티로 추가 된다.

      var TEST1 = "TEST1";
      var TEST2 = "TEST2";
      console.log(window.TEST1) // TEST1
      console.log(window.TEST2) // TEST2
      function TEST3 (a) => {
        ....
      }
      console.log(window.TEST3) // TEST3(a)
      • 전역 변수는 전역 객체 프로퍼티의 또는 전역 객체의 실행 문맥에 들어있는 환경 레코드의 프로퍼티이다.
      • 최상위 레벨에 선언된 변수와 함수는 프로그램을 평가하는 시점에 환경레코드에 추가 된다. 평가 단계에서 이미 객체 환경 레코드에 추가된 상태이기 때문에 어느 위치에서 작성해도 사용할수 있게 된다. 이게 호이스팅(hoisting)이다.
      • var 문과 함수 선언문으로 선언한 전역 변수는 [[Configualble]] 속성이 false로 설정되어 있어서 delete연산으로 삭제가 불가능하다.
      • var문을 사용하지 않고 변수를 선언해서 값을 할당하면 프로그램을 실행하는 도중에 디스 바인딩 컴포넌트가 가리키는 객체의 프로퍼티로 추가된다. 디스 바인딩 컴포넌트가 전역객체를 가리키므로 결국 전역 객체가 되는 것이다. 하지만 [[Configualble]] 속성이 true로 되어 있기 때문에 delete연산으로 삭제가 가능하다.
  • 프로그램 실행과 실행 문맥

    • 프로그램이 평간된 뒤 프로그램이 실행되며, 프로그램은 실행 문맥(Excutable Context) 안에서 실행된다.
    • 실행 문맥은 실행 가능한 코드(전역 코드, 함수 코드, eval 코드)별로 생성된다.

      • 실행 문맥은 스택(stack)구조로 관리된다. 이를 호출 스택(call stack)이라 부른다.
      • 전역 코드가 가장 먼저 실행된다. 전역 코드안에 함수가 있다면 함수를 실행 하기위한 문맥을 스택에 push하고 함수가 끝나면 이를 pop한다. 이때 함수가 중첩함수라면 중첩 함수의 실행 문맥을 새로 만들어서 스택에 push-pop한다.
  • 싱글 스레드

    • 자바스크립트는 싱글 스레드 방식이다. 즉, 실행 문맥 단위의 작업을 차례대로 실행 하므로 실행 문맥(함수나 코드)하나의 작업이 끝날 때까지 또 다른 실행 문맥의 작업을 실행하지 않는다.
  • 환경 레코드와 지역 변수

    • 함수 호출시 내부적으로 발생하는 일

      (1)함수 호출
      (2)실행 코드 중지
      (3)실행 문맥 생성
      (4)실행 문맥으로 이동
      (5)호출 스택에 Push
      (6)렉시컬 환경 컴포넌트 생성
      (7)함수의 환경 기록, 디스 바인딩(This Binding) 컴포넌트에 그 함수를 호출한 객체를 기록
      (8)함수안의 코드가 순차적으로 실행
      (9)함수 종료
      (10호출한 코드로 이동, 만들어진 실행 문맥과 렉시컬 환경 컴포넌트가 메모리에서 삭제
      • 디스 바인딩(This Binding)에 해당 함수를 호출하는 객체가 기록되는데, 이것이 This 값을 결정 짓는다.
  • This

    • 함수가 호출되어 실행되는 시점에 This 값이 결정된다.
    • This는 함수가 호출되었을 때, 그 함수가 속해 있던 객체의 참조이다.
    const add = {
      x: 10,
      y: 11,
      sum: function() {
        console.log(this);
        return this.x + this.y;
      }
    };
    console.log(add.sum());
    // 결과
    // { x: 10, y: 11, sum: [Function: sum] }
    // 21
    //
    • sum이 속한 객체는 add이다. sum 메서드가 호출되는 실행 문맥의 디스 바인딩 컴포넌트가 가리키는 객체는 add가 된다.
    • 다양한 상황별 This
    • 최상위 레벨 코드의 this

      • 전역 객체를 가리킨다. 실행 문맥이 초기화될 때 디스 바인딩 컴포넌트가 전역 환경을 가리킨다.
    • 이벤트 처리기 안에 있는 this

      • 이벤트가 발생한 요소 객체를 가리킨다.
    • 생성자 함수 안에 있는 this

      • 사용자가 정의한 생성자 함수 안에 있는 this는 생성자로 생성한 객체를 가리킨다.
    • 생성자의 prototype 메서드 안에 있는 this

      • 생성자의 prototype 메서드 있는 this는 생성자로 생성한 객체를 가리킨다.
    • 직접 호출한 함수 안에 있는 this

      • 최상위 레벨에서 호출한 함수 안의 this는 전역객체를 가리킨다.
      • 어떤 객체를 부여 호출하면 this는 해당 객체를 가리킨다.
    • apply,call 메서드로 호출한 함수 안에 있는 this

      • applycall 메서드를 사용하면 함수를 호출할 때 this가 가리키는 객체를 바꿀수 있다. 즉 두 함수는 함수 객체가 실행되는 실행 문맥의 디스 바인딩 컴포넌트가 가리키는 객체를 설정 할 수 있다.
  • 유효범위 체인(스코프 체인)

    • 간단히 정리하면 유효 범위 안에 없는 식별자를 찾을 경우 외부 렉시컬 환경의 참조를 따라 찾는다고 보면 된다.

이 코드는 모던 자바스크립트 입문(徹底マスターJavaScriptの教科書) 에서 인용한 것입니다.
[ISBN #978-4797388640]. Copyright 2017 by 磯博

Loading script...