JavaScript

7-3. 실행 컨텍스트

문정훈 2022. 1. 30. 01:51

1. 소스코드의 평가와 실행 도입 및 용어정리

1) 평가와 실행 도입

ECMAScript에서는 소스코드를 4가지의 타입으로 분류한다 

  1. 전역 코드 
    전역에 존재한다. 
  2. 함수 코드
    함수 내부에 존재하는 소스코드이다. 
  3. eval 코드
    빌트인 전역 함수인 eval 함수에 인수로 전달하여 실행되는 소스코드
  4. 모듈 코드 
    모듈 내부에 존재하는 소스코드이다. 

자바스크립트에서 모든 소스코드는 '평가'과정을 거친 뒤 '실행' (런타임) 과정을 거치게 된다. 

'평가' 과정은 실행에 앞서 코드를 실행하기 위한 준비를 하는 단계이며 '실행' 단계는 실제 런타임을 말한다.

소스코드에서 '평가' 과정에서는 어떤 작업이 일어나며 '실행' 과정에서는 어떤 작업이 일어나는지 설명한다.

 

2) 실행 컨텍스트

소스 코드가 실행되면 스코프, 식별자, 코드 실행 순서 등의 관리가 필요하다.

실행 컨텍스트란 소스코드를 실행하는데 필요한 환경을 제공한다. 코드의 실행 결과를 실제로 관리하는 영역이다.

 

소스코드가 평가되면 해당 소스코드의 실행 컨텍스트가 생성되는데 실행 컨텍스트는  렉시컬 환경 (객체)를 가진다

렉시컬 환경(객체)를 통해 소스코드의 식별자와 스코프가 관리된다. 

즉 렉시컬 환경은 해당 소스코드의 스코프의 실제 구현체라고 봐도 된다. 

소스코드가 평가되면 실행 컨텍스트를 만든다고 했는데 이런 실행 컨텍스트들은 실행 컨텍스트 스택으로 그 순서가 관리 된다.

 

3) 렉시컬 환경(중요)

렉시컬 환경은 실행 컨텍스트의 Component인 객체인데 렉시컬 환경(객체)는 키와 값을 통해 스코프(전역, 함수, 블록 스코프)를 생성하고 식별자를 키로 등록하며 식별자에 바인딩된 값을 관리하는 객체이다. 

즉 렉시컬 환경이란 소스코드의 렉시컬 스코프의 실체이다. 

아래 소스코드의 평가와 실행 과정을 보면 용어들이 더 잘 정리된다.


 

2. 소스코드의 평가 과정

1) 평가 과정

  1. 전역 실행 컨텍스트 생성
  2. 전역 렉시컬 환경 생성
    2.1. 전역 환경 레코드 생성 
          2.1.1 객체 환경 레코드 생성
          2.1.2 선언적 환경 레코드 생성
    2.2 this 바인딩
    2.3 외부 렉시컬 환경에 대한 참조 결정

위 순서는 '평가'과정의 진행 과정을 정리한 것이다. 하나하나 설명하면

소스코드가 평가되면 실행 컨텍스트 스택에 소스코드의 실행 컨텍스트를 생성하고 스택에 push 한다.

실행 컨텍스트는 렉시컬 환경 객체를 Component로 가진다.  (렉시컬 환경은 실제론 객체이다)

렉시컬 환경은 전역 환경 레코드선언적 환경 레코드 객체를 가진다. 

 

 

● 전역 환경 레코드

전역 환경 레코드는 BindingObject 객체를 가지는데 이 객체를 통해 var 타입과 함수 선언문의 key 값들이 전역 객체가 가지는 식별자로써 등록되게 된다. 

var 타입의 변수가 key가 되며 함수 선언문은 함수 정의 즉 함수 이름이 key 값이 된다. 

 

'평가' 과정에서는 var 타입의 key의 값으로 undefind를 할당한다.

그리고 함수 선언문은 함수의 이름을 key로 가지며 그 값으로 함수 객체가 바로 생성되어 값으로 할당된다. 

 

함수의 선언문을 포함하는 코드 블록의 '평가'과정이 진행되면 함수 정의 foo를 key로 지정하고 함수 객체를 즉시 할당한다. (함수의 평가가 진행된다.!! 여기서의 평가는 함수의 실행 컨텍스트를 생성하고 하는 과정이 아닌 단순히 [[Environment]]의 값이 결정된다는 점에 집중하자!!)

함수 객체를 할당할 때 즉 함수의 평가 과정이 진행되므로 그 함수의 [[Environment]]의 값이 결정되는데, 함수 선언문을 포함하는 코드 블록의 평가 과정에서 함수 선언문의 상위 스코프가 결정되고 그 상위 스코프는[[Environment]]이라는 내부 슬롯이 가리킨다.

 

함수가 호출되면 함수의 코드가 평가가 진행되는데 평가 과정이 진행되면 외부 렉시컬 환경에 대한 참조를 결정하는 값으로 이 내부 슬롯의 값이 사용 된다. 

 

즉 함수의 상위 스코프는 그 함수가 호출되는 시점(평가 되는 시점)의 상위 스코프가 아닌 함수가 선언된 코드 블록의 평가 과정에서 그 코드 블록을 상위 스코프로 결정하고 이는 바뀌지 않는다. (이것이 렉시컬 스코프의 개념이었다.)

 

위 문장이 이 블로그 절에서 내가 하고 싶은 핵심 내용이다. !!!

 

 

● 선언적 환경 레코드

이 곳에는 let, const 타입의 식벼자들이 저장되는 공간으로 let과 const 변수는 전역 객체의 프로퍼티가 되지 않고 개념적인 블록 내에 존재하게 된다. 이 개념적인 블록이 전역 환경 레코드의 선언적 환경 레코드이다. 

 

 

※  여기까지 요약 정리

소스 코드의 평가 과정에서는 var 타입의 값으론 undefind값이 할당되고 let, const는 일시적 사각지대 상태가 되며 

함수 선언문은 함수의 이름이 key가 되며 그 값으로 함수 객체가 즉시 할당되고 함수의 [[Environment]] 내부 슬롯의 값으로 함수 선언문을 포함하는 코드 블록의 평가 과정에서 함수 선언문의 상위 스코프가 된다. 

 

 

● this 바인딩

위 과정까지 진행된 후 this바인딩이 결정된다. 

전역 환경 레코드의 [[GlobalThisValue]] 내부 슬롯에 this가 바인딩되는데 일반 함수의 경우 this 바인딩은 전역 객체가 되며 생성자 함수, 객체, 클래스 등의 this 바인딩은 해당 this 가 선언되 객체에 바인딩된다. 

 

 

 

● 외부 렉시컬 환경 참조

현재 평가 중인 소스코드는 실행 컨텍스트를 가진다 하였는데 전역 환경 레코드의 프로퍼티인 외부 렉시컬 환경 참조라key의 값으로 현재 평가 중인 스코프의 상위 스코프를 가리킨다. 

그 값은 전역 환경 레코드가 가지는 내부 슬롯인 [[Environment]] 의 값이다. 

[[Environment]]에 값이 어떻게 할당되는지 위 글을 읽어 이해했다면 전역 환경 레코드의 외부 렉시컬 참조의 값은 결국

[[Environment]]값이므로 이해가 될 것이다..