-
실행 문맥(Execution Context)란?
소스코드를 실행하는데 필요한 환경과 결과를 관리하는 영역입니다.
식별자를 등록하고 관리하는 스코프와 코드 실행 순서 관리를 구현한 내부 메커니즘으로 컨텍스트를 실행 및 관리합니다.
식별자와 스코프는 렉시컬 환경으로 관리하고, 코드 실행 순서는 실행 컨택스트 스택으로 관리합니다.
소스 코드의 타입
ECMAScript는 소스코드를 4가지 타입으로 구분합니다.
1) 전역 코드
- 전역에 존재하는 소스코드를 말합니다. 전역에 정의된 함수, 클래스 등의 내부코드는 포함 X
- 전역 변수를 관리하기 위해 최상위 스코프인 전역 스코프를 생성합니다.
2) 함수 코드
- 함수 내부에 존재하는 소스코드를 말합니다. 함수 내부에 중첩된 코드는 포함 X
- 지역 스코프를 생성하고, 지역 / 매개 변수 및 Arguments 객체를 관리합니다.
- 지역 스코프를 전역 스코프와 연결합니다.
3) eval 코드
- 빌트인 전역 함수인 eval 함수에 인수로 전달되어 실행되는 소스코드를 말합니다.
- 자신의 독자적인 스코프를 생성합니다.
4) 모듈 코드
- 모듈 내부의 존재하는 코드를 말합니다.
소스코드의 평가와 실행
모든 소스코드는 실행에 앞서 평과와 실행 과정을 나누어 거칩니다.
1) 평가
소스코드의 평가 과정에서는 실행 컨텍스트를 생성하고 변수, 함수등의 선언문만 먼저 실행하여 생성된 변수나 함수 식별자를 키로 실행 컨텍스트가 관리하는 스코프에 등록합니다.
2) 실행
평가 과정이 끝나면, 선언문을 제외한 소스코드가 순차적으로 실행(=런타임) 됩니다.
이 때, 소스코드 실행에 필요한 정보, 즉 변수나 함수의 참조를 실행 컨텍스트가 관리하는 스코프에서 검색하여 취득합니다.
그리고 변수 값의 변경 등 소스코드의 실행 결과는 다시 실행 컨텍스트가 관리하는 스코프에 등록 됩니다.
예시
다음과 같은 코드가 실행된다고 생각해봅시다.
var x = 1;
그렇다면 우선적으로 자바스크립트 엔진은 평가 과정에서 아래와 같은 변수 선언문 실행합니다.
이 때, 생성된 변수 식별자 x는 실행 컨텍스트가 관리하는 스코프에 등록되고 undefined로 초기화 됩니다.
* let은 평가와 초기화와 동시에 일어나지 않습니다.
var x;
소스코드 평가 과정이 끝나면, x라는 변수에 1을 할당 해주면 되는데요. 이 때, x가 선언된 변수인지 확인 하기 위해서 실행 컨텍스트의 스코프에 있는지 확인을 합니다.
x = 1;
실행 컨텍스트의 역할
아래의 코드를 실행 했을 때, 자바스크립트 엔진은 이 예제를 어떻게 평가하고 실행할까요?
const x = 1; const y = 2; function foo(a) { const x = 10; const y = 20; console.log(a + x + y); } foo(100); console.log(x + y);
1) 전역 코드 평가
- 전역 코드를 실행하기에 앞서, 전역 코드 평가 과정을 거치며 실행을 위한 준비를 합니다.
- 평가 과정에서는 선언문만 먼저 실행하고, 그 결과 생성된 변수와 전역 함수가 전역 스코프에 등록이 됩니다.
2) 전역 코드 실행
- 전역 코드 평가 과정이 끝나면, 런타임이 시작되어 전역 코드가 순차적으로 실행됩니다.
- 이 때, 전역 변수에 값이 할당되고 함수가 호출됩니다.
- 순차적으로 진행하면서 함수를 만나면 전역 코드의 실행을 중단하고 코드 실행 순서를 변경하여, 함수 내부로 진입합니다.
3) 함수 코드 평가
- 함수 내부의 문들을 실행 하기에 앞서, 코드 평가 과정을 거치고 실행을 위한 준비를 합니다.
- 이 때, 매개변수와 지역 변수 선언문이 먼저 실행되고, 그 결과는 지역 스코프에 저장이 됩니다.
4) 함수 코드 실행
- 함수 코드 평가가 끝나면, 런타임이 시작되어 함수 코드가 순차적으로 실행 됩니다.
- console 호출을 위해 console 을 스코프 체인을 통해 검사하고 이와 동시에 징겨 스코프가 전역 스코프와 연결됩니다.
- console 식별자는 전역 객체의 프로퍼티로 존재하고, 이를 통해 log 프로퍼티에 접근합니다.
- console.log 메서드에 인수로 전달된 a + x + y 를 평가하고, 값을 찾습니다.
- 실행이 종료되면 함수 호출 이전으로 되돌아가 전역 코드 실행을 계속합니다.
실행 컨텍스트 스택
실행컨텍스트는 스택 자료구조를 통해, 상태를 관리합니다.
const x = 1; function foo() { const y = 2; function bar() { const z = 3; console.log(x + y + z); } bar(); } foo(); // 6
상단의 코드는 아래와 같이 스택에 쌓이면서 작동합니다.
렉시컬 환경
스코프와 식별자를 관리하는 역할을 수행합니다.
const x = 1; function foo() { const y = 2; console.log(x + y); }
위의 코드는 렉시컬 환경에서 다음과 같이 표시됩니다.
렉시컬 환경은 키와 값을 갖는 객체 형태의 스코프를 생성하여 식별자를 키로 등록하고, 식별자에 바인딩된 값을 관리합니다.
실행 컨텍스트는 LexicalEnvironment 컴포넌트와 VariableEnviroment 컴포넌트로 구성이 됩니다.
생성 초기에 렉시컬 컴포넌트와 변수 컴포넌트는 하나의 동일한 렉시컬 환경을 참조합니다. 이 후, 몇 가지 상황을 만나면 각 컴포넌트에 맞는 렉시컬 컴포넌트를 생성합니다.
렉시컬 환경 Detail
- 렉시컬 환경은 환경 레코드와 외부 렉시컬 환경에 대한 참조로 이루어져있습니다.
- 환경레코드는 스코프에 포함된 식별자를 등록하고, 등록된 식별자에 바인딩 된 값을 관리하는 역할을 수행합니다.
- 외부 렉시컬 참조는 상위 스코프를 가르키면, 이를 바탕으로 단방향 리스트를 통해 스코프 체인을 구현합니다.
실행 컨텍스트의 생성과 식별자 검색 과정
아래의 코드 예제를 통해서, 실행 컨텍스트가 어떻게 생성되고 코드 실행 결과를 관리하는지 자세히 살펴보겠습니다.
var x = 1; const y =2; function foo (a) { var x = 3; const y = 4; function bar (b) { const z = 5; console.log( a + b + x + y + z ); } bar(10); } foo(20); // 42
1. 전역 객체 생성
전역 코드의 평가 이전에, 전역 객체를 생성합니다.
2. 전역 코드 평가
소스코드가 로드 되면, 자바스크립트 엔진은 "전역" 코드를 평가합니다. 평가는 아래의 순서대로 진행됩니다.
1. 전역 실행 컨텍스트 생성 2. 전역 렉시컬 환경 생성 - 2.1 전역 환경 레코드 생성 2.1.1 객체 환경 레코드 생성 2.1.2 선언적 환경 레코드 생성 - 2.2 this 바인딩 - 2.3 외부 렉시컬 환경에 대한 참조 결정
[1] 전역 실행 컨텍스트 생성
'Develop > JavaScript' 카테고리의 다른 글
이터레이터 & 제네레이터 ( iterator & generator ) (0) 2021.08.09 [ JavaScript ] 정규식 ( Regular Expression) (0) 2021.08.03 [ JavaScript ] let vs var (0) 2021.07.14 [ JavaScript ] This 란 ? (0) 2021.07.14 [JavaScript] This 란? ( 우아한 Tech ) (0) 2021.07.02 댓글