본문 바로가기
개발서적/모던 자바스크립트 Deep Dive

실행 컨텍스트 (모던 자바스크립트 Deep Dive)

by 사과넹 2024. 4. 16.
반응형

  • 실행 컨텍스트의 개념을 이해하면 자바스크립트의 전반적인 이론들을 이해할 수 있다.
    • 꼭 완벽 이해해보자..!

 

23.1 소스코드의 타입

  • 소스코드에 따라 실행 컨텍스트를 생성하는 과정이 다 다르다.
    • 코드가 평가될 때, 실행 컨텍스트를 생성한다.
  1. 전역 코드
    1. 전역 스코프 생성
    2. 전역 변수 관리
  2. 함수 코드
    1. 지역 스코프 생성
    2. 지역 변수, 매개변수, 인수 관리
    3. 스코프 체인을 연결해야한다.
  3. eval 코드
    1. 자신만의 실행 컨텍스트 생성
    2. 이거 사용하지 말자.
  4. 모듈 코드
    1. 독립적인 모듈 스코프 생성

 

24.2 소스코드의 평가와 실행

  • 평가 과정에서 실행 컨텍스트를 생성하고, 식별자를 키로 실행 컨텍스트가 관리하는 스코프에 등록
    • 스코프 : 렉시컬 환경의 환경 레코드
  • 평가가 끝나면 런타임이 시작되고, 실행에 필요한 정보들을 실행 컨텍스트가 관리하는 스코프에서 검색하여 취득한다. 값 변경도 실행 컨텍스트에서 관리된다.

 

23.3 실행 컨텍스트의 역할

  • 전역 변수의 평가 → 실행 컨텍스트(전역 스코프 등록) → 런타임 시작 → 함수 호출 → 함수 내부 평가 → 실행 컨텍스트(지역 스코프 등록) → 함수 내부 런타임 실행 → 함수 호출 끝 → 이전에 실행하던 곳에서 다시 시작
  • 코드가 동작하기 위하여 코드를 평가하는 과정에서 먼저 식별자와 값을 수집하고, 실행 때 필요한 정보들을 스코프 체인을 기반으로 관리하여 내어주거나 수정해주며 실행하다가 평가 후 재실행을 하게 될 시 어디서부터 재시작해야되는지 등을 기억해준다.
    • 프로그램이 실행될 수 있도록 조력자 역할을 톡톡히 한다!

 

23.4 실행 컨텍스트 스택

  • stack 자료구조로 관리된다.
    • 자바스크립트 배열 프로토타입 메서드의 push() , pop() 의 개념
  • 전역 실행 컨텍스트가 stack의 가장 아래에 깔리고, 함수 호출 순서에 따라 stack이 push되며, 해당 실행컨텍스트에서 더이상 할일이 없을 때, 실행 컨텍스트가 pop되어 stack 에서 사라진다.
  • 즉, 최상위 존재하는 실행 컨텍스트는 현재 실행 중인 코드의 실행 컨텍스트이다!

 

23.5 렉시컬 환경

  • 스코프와 식별자를 관리. 참조를 기록하는 자료구조
    • 실행 중 변수를 만나면 해당 변수를 스코프 체인에 따라 탐색해주고, 값이 존재하면 내어줌.
  • 렉시컬 환경은 두 가지의 컴포넌트로 존재한다.
    • 환경 레코드
      • 스코프에 포함된 식별자를 등록하고 식별자에 바인딩된 값을 관리하며 타입에 따라 관리한다.
    • 외부 렉시컬 환경에 대한 참조
      • 상위 스코프를 참조. 해당 실행 컨텍스트에서 찾을 수 없는 식별자를 상위 스코프로 올라가며 탐색하며 스코프 체인을 구현한다.

 

23.6 실행 컨텍스트의 생성과 식별자 검색 과정

23.6.1 전역 객체 생성

  • 전역 코드가 평가되기전 전역 객체가 먼저 생성된다.
    • 빌트인 객체, 호스트 객체 등이 생성된다.

 

23.6.2 전역 코드 평가

  • 전역 코드 평가에 대한 순서는 아래와 같다.
  1. 전역 실행 컨텍스트 생성
  2. 전역 렉시컬 환경 생성
    1. 전역 환경 레코드 생성
      1. 객체 환경 레코드 생성
      2. 선언적 환경 레코드 생성
    2. this 바인딩
    3. 외부 렉시컬 환경에 대한 참조 결정

 

1. 전역 실행 컨텍스트 생성

  • 전역 실행 컨텍스트를 stack에 push

2. 전역 렉시컬 환경 생성

  • 전역 렉시컬 환경을 전역 실행 컨텍스트에 바인딩한다.

2-1. 전역 렉시컬 환경 생성

  • 전역 스코프, 전역 객체의 빌트인 프로퍼티와 함수, 표준 빌트인 객체 제공
  • 전역 환경 레코드
    • 객체 환경 레코드
      • var 키워드로 선언한 전역 변수, 함수 선언문, 빌트인 전역 프로퍼티와 함수, 표준 빌트인 객체
      • 위의 객체와 변수들은 BindingObject 를 통해 전역 객체의 프로퍼티와 메서드가 된다.
      • 변수 호이스팅은 코드 평가 시점에서 undefined 로 초기화되고, 함수 호이스팅은 생성된 함수 객체로 즉시 할당한다.
    • 선언적 환경 레코드
      • let , const 로 선언한 전역 변수
      • 두 키워드 또한 호이스팅이 일어나지만 일시적 사각지대(TDZ)현상으로 인해 변수 선언문 이전에 참조할 수 없다.

2-2. this 바인딩

  • 전역 환경 레코드의 [[GlobalThisValue]] 내부 슬롯에 this가 바인딩 된다.
    • 일반적으로 전역 코드에서 this는 전역 객체이다.

2-3. 외부 렉시컬 환경에 대한 참조

  • 단방향 링크드 스코프 체인을 구현한다.
  • 전역 코드일 경우 외부 렉시컬 환경에는 null이 할당된다.
    • 전역 코드의 상위 스코프는 없기 때문.

 

23.6.3 전역 코드 실행

  • 전역 변수에 값이 할당되고, 함수가 호출된다.
  • 사용할 변수의 식별자가 선언되어 어느 스코프의 식별자를 참조하면 되는지를 결정하는 단계가 필요하다.
    • 식별자 검색이 이뤄지고, 현재 실행중인 실행 컨텍스트를 시작으로 검색이 이뤄진다.
    • 만약 현재 실행중인 실행 컨텍스트에서 해당 식별자를 찾을 수 없다면 외부 렉시컬 환경에 대한 참조가 일어난다.

 

23.6.4 전역 함수 코드 평가

  • 함수가 호출되면 현재 평가 중인 코드의 실행을 중단한다.
    • 함수 내부 코드로 제어권이 이동하며 함수 코드 평가를 시작한다.
  • 함수 코드의 평가 순서는 아래와 같다.
  1. 함수 실행 컨텍스트 생성
  2. 함수 렉시컬 환경 생성
    1. 함수 환경 레코드 생성
    2. this 바인딩
    3. 외부 렉시컬 환경에 대한 참조 결정

 

1. 전역 함수 실행 컨텍스트 생성

  • 해당 함수 실행 컨텍스트를 stack에 push한다.

2**. 전역 함수 렉시컬 환경 생성**

  • 함수 렉시컬 환경을 해당 실행 컨텍스트에 바인딩한다.

2-1. 전역 함수 환경 레코드 생성

  • 매개변수, arguments 객체, 함수 내부 선언된 지역 변수, 중첩 함수를 등록하고 관리

2-2. this 바인딩

  • 함수 환경 레코드의 [[ThisValue]] 내부 슬롯에 this가 바인딩 된다.
  • 호출 방식에 따라 this에 바인딩되는 객체가 달라질 것이다.
    • 일반 함수의 경우 this 는 전역 객체

2-3. 외부 렉시컬 환경에 대한 참조 결정

  • 함수가 전역에서 정의되었다면 외부 렉시컬 환경은 전역 렉시컬 환경의 참조가 할당된다.
  • 자바스크립트는 렉시컬 스코프를 따르기 때문에 함수가 정의된 스코프에서 상위 스코프를 결정한다.
  • 이 때, 함수의 상위 스코프를 함수 객체의 내부 슬롯 [[Environment]]에 저장한다.
    • 이는 렉시컬 스코프를 구현하는 메커니즘
    • 클로저를 이해할 수 있는 단서!!!

 

23.6.5 전역 함수 코드 실행

  • 인수 할당과 변수 할당문이 실행되어 지역 변수에 값이 할당된다.
    • 식별자를 결정하기 위해 렉시컬 환경에서 식별차를 검색하고, 없다면 외부 렉시컬 환경에 대한 참조가 가리키는 렉시컬 환경으로 이동할 것이다.
  • 중첩 함수가 호출된다.

 

23.6.6 중첩 함수 코드 평가

  • 중첩 함수가 호출되는 순간 해당 중첩 함수 내부로 코드의 제어권이 이동한다. 그리고 평가를 시작한다.
  • 해당 함수 실행 컨텍스트를 stack에 push한다.

 

23.6.7 중첩 함수 코드 실행

  • 지역 변수에 인수가 할당된다.

 

1. console 식별자 검색

  • console 식별자를 현재 실행 중인 실행 컨텍스트에서 검색한다.
    • 찾지 못했다면 외부 렉시컬 환경에 대한 참조가 가리키는 상위 함수에서 검색하고, 거기에도 없다면 상위 함수의 외부 렉시컬 환경에 대한 참조가 가리키는 상위 렉시컬 환경으로 이동한다.

2. log 메서드 검색

  • console 객체의 프로토타입 체인을 통해 메서드를 검색한다.
console.hasOwnProperty('log'); // true

2. a + b + x + y + z 의 평가

  • 표현식을 평가하기 위해 실행 중인 컨텍스트에서 부터 외부 렉시컬환경에 대한 참조로 이어지며 계속 검색해 간다.

3. console.log 메서드 호출

  • 평가한 표현식을 console.log 메서드에 전달하여 호출 !!

 

23.6.8 중첩 함수 코드 실행 종료

  • 실행 컨텍스트 stack 에서 중첩 함수에 대한 실행 컨텍스트를 pop!
  • 스택에서는 제거되었지만 해당 함수의 렉시컬 환경까지 소멸되지 않고, 아무에게도 참조되지 않을 때, 가비지 컬렉터가 주워간다.

 

23.6.9 전역 함수 코드 실행 종료

  • 실행 컨텍스트 stack 에서 전역 함수에 대한 실행 컨텍스트를 pop!

 

23.6.10 전역 코드 실행 종료

  • 실행 컨텍스트 stack에서 전역 코드에 대한 실행 컨텍스트를 pop!
  • 전역 코드 실행 컨텍스트가 스택에서 사라지면 실행 컨텍스트 스택에는 아무것도 남지 않는다.

 

23.7 실행 컨텍스트와 블록 레벨 스코프

  • if 문의 코드블록이 실행되면 해당 블록을 위한 블록 레벨 스코프를 생성하고, 이를 위해 선언적 환경 레코드를 갖는 렉시컬 환경을 새롭게 생성하여 기존 전역 렉시컬 환경을 교체한다.
    • 실행 컨텍스트를 생성하는게 아닌 블록 레벨의 렉시컬 환경을 생성하는 것이다.
      • 그리고 해당 렉시컬 환경에서 찾을 수 없는 식별자가 생기면 외부 렉시컬 환경에 의한 참조를 구현한다.
    • for 문의 경우 반복문이 실행될 때마다 값을 유지하고 있어야하기 때문에 선언적 환경 레코드를 갖는 렉시컬 환경에서 식별자의 값을 유지한다.
728x90
반응형