# 소스코드의 타입
소스코드(실행 가능한 코드)를 4가지 타입으로 구분한다.
4가지 타입의 소스코드는 실행 컨텍스트를 생성한다.
소스코드의 타입 | 설명 |
전역 코드 | 전역에 존재하는 소스코드 |
함수 코드 | 함수 내부에 존재하는 소스코드 |
eval 코드 | 빌트인 전역함수인 eval함수에 인수로 전달되어 실행되는 소스코드 |
모듈 코드 | 모듈 내부에 존재하는 소스코드 |
## 소스코드를 4가지 타입으로 구분하는 이유
→ 소스코드의 타입에 따라 실행 컨텍스트를 생성하는 과정과 관리 내용이 다르다.
전역, 함수, eval, 모듈 코드가 각각 평가가 되면, 전역, 함수, eval, 모듈 실행 컨텍스트가 생성된다.
# 소스코드의 평가와 실행
자바스크립트 엔진은 소스코드를 2개의 과정, '소스코드의 평가'와 '소스코드의 실행' 과정을 나누어 처리한다.
1/ 소스코드의 평가
- 실행 컨텍스트 생성
- 변수, 함수 등의 선언문만 먼저 실행
- 생성된 변수나 함수 식별자를 key로 실행 컨텍스트가 관리하는 스코프(렉시컬 환경의 환경 레코드)에 등록
2/ 소스코드의 실행
선언문을 제외한 소스코드가 순차적으로 실행
즉, 런타임 시작.
소스코드 실행에 필요한 정보, 즉 변수나 함수의 참조를 실행 컨텍스트가 관리하는 스코프에서 검색해서 취득.
변수 값의 변경 등 소스코드의 실행 결과는 다시 실행 컨텍스트가 관리하는 스코프에 등록
예를 들어, 아래와 같은 소스코드가 실행된다고 생각해보자.
var x;
x = 1;
자바스크립트 엔진은 위 예제를 2개의 과정으로 나누어 처리한다.
1/ 소스코드 평가
변수 선언문인 var x; 실행
생성된 변수 x는 실행 컨텍스트가 관리하는 '스코프'에 등록
var선언문이므로 undefined으로 초기화.
실행 컨텍스트 | |
x | undefined |
2/ 소스코드 실행
변수 선언문인 var x;는 '소스코드 평가' 과정에서 이미 실행 완료.
할당문 x = 1 실행.
이 때 변수 x에 값을 할당하려면, 먼저 x변수가 선언된 변수인지 확인해야한다.
실행 컨텍스트가 관리하는 스코프에 x 변수가 등록되어 있는지 확인.
즉, x변수가 선언된 변수인지 확인.
만약 x 변수가 실행 컨텍스트가 관리하는 스코프에 등록되어 있다면,
x변수는 선언된 변수, 즉 소스코드 평가 과정에서 선언문이 실행되어 등록된 변수.
x변수가 선언된 변수라면, 값을 할당하고 할당 결과를 실행 컨텍스트가 관리하는 스코프에 등록하여 관리.
실행 컨텍스트 | |
x | 1 |
# 실행 컨텍스트의 역할
다음 예제는 전역 코드와 함수 코드로 구성되어 있다.
자바스크립트 엔진이 이 예제를 어떻게 평가하고 실행할지 생각해보자.
// 전역변수 선언
const x = 1;
const y = 2;
// 함수 정의
function foo() {
// 지역변수 선언
const x = 10;
const y = 20;
// 메서드 호출
console.log(a + x + y);
};
//함수 호출
foo(100);
// 메서드 호출
console.log(x + y);
1. 전역 코드 평가
먼저 전역코드 평가 과정을 거친다.
소스코드 평가 과정에서는 '선언문'만 먼저 실행한다.
전역 코드의 변수 선언문과 함수 선언문이 먼저 실행된다.
→ 생성된 전역변수, 전역 함수가 실행 컨텍스트가 관리하는 전역 스코프에 등록된다.
** 함수 선언문(선언식)의 형태는 아래와 같다.
function 함수명() {
구현 로직
}
// 예시
function funcDeclarations() {
return 'A function declaration';
}
funcDeclarations(); // 'A function declaration'
따라서
실행 컨텍스트 | |
x | - (초기화x) |
y | - (초기화x) |
foo | function(){...} |
** 함수 선언문의 경우에는 자바스크립트 엔진이 런타임 이전에 먼저 실행(소스코드 평가 시)되어 함수 자체를 호이스팅시킨다.
// 전역변수 선언
const x = 1;
const y = 2;
// 함수 정의
function foo() {
// 지역변수 선언
const x = 10;
const y = 20;
// 메서드 호출
console.log(a + x + y);
};
//함수 호출
foo(100);
// 메서드 호출
console.log(x + y);
2. 전역 코드 실행
전역 코드 평가가 끝나면, 런타임이 시작되어 전역 코드가 순차적으로 실행된다.
이 때, 전역 변수에 값이 할당되고 함수가 호출된다.
함수가 호출되면 순차적으로 실행되던 전역코드의 실행을 일시중단하고 코드 실행 순서를 변경하여 함수 내부로 진입한다.
1) 위 예시에서는 위에서부터 차례대로 x, y에 각각 1, 2를 할당하는 것부터 시작한다.
x = 1, y = 2;
실행 컨텍스트 | |
x | 1 |
y | 2 |
foo | function () {...} |
2) foo(100) 함수 호출. foo함수 내부로 진입
3. 함수 코드 평가
함수 호출에 의해 코드 실행 순서가 변경되어 함수 내부(foo 함수)로 진입.
함수코드 평가를 한다.
- 매개변수, 지역 변수 선언문이 먼저 실행
const x, const y;
- 생성된 매개변수, 지역 변수가 실행컨텍스트가 관리하는 지역 스코프에 등록된다.
- 함수 내부에서 지역 변수처럼 사용할 수 있는 arguments객체가 생성되어 지역 스코프에 등록된다.
- this 바인딩 결정된다.
실행 컨텍스트 | |
x | - |
y | - |
4. 함수 코드 실행
함수 코드 평가과정이 끝나면 런타임이 시작되어 함수코드가 순차적으로 실행된다.
- 매개변수와 지역 변수에 값 할당
x = 10, y = 20;
- console.log 메서드 호출된다.
console.log(a + x + y);
실행 컨텍스트 | |
x | 10 |
y | 20 |
console.log 메서드의 실행이 종료되면 함수 코드 실행 과정이 종료되고, 함수 호출 이전으로 되돌아가 전역 코드 실행을 계속한다.
이처럼 코드가 실행되려면
- 스코프를 구분하여 식별자와 바인딩된 값이 관리되어야 한다.
- 중첩 관계에 의해 스코프 체인을 형성하여 식별자를 검색할 수 있어야 한다.
- 전역 객체의 프로퍼티도 전역 변수처럼 검색할 수 있어야 한다.
- 함수 호출이 종료되면 함수 호출 이전으로 되돌아가기 위해, 현재 실행중인 코드와 이전에 실행하던 코드를 구분하여 관리해야 한다.
이처럼 코드가 실행되려면 다음과 같이 스코프, 식별자, 코드 실행 순서 등의 관리가 필요하다.
이 모든 것을 관리하는 것이 바로 '실행 컨텍스트'이다.
실행 컨텍스트는 소스코드를 실행하는 데 필요한 환경을 제공하고, 코드의 실행 결과를 실제로 관리하는 영역.
좀 더 구체적으로 말해, 실행 컨텍스트는 식별자(변수, 함수, 클래스 등의 이름)를 등록하고 관리하는 스코프와 코드 실행 순서 관리를 구현한 내부 메커니즘으로, 모든 코드는 실행 컨텍스트를 통해 실행되고 관리된다.
- 식별자와 스코프 : 실행 컨텍스트의 '렉시컬 환경'으로 관리.
- 코드 실행 순서 : '실행 컨텍스트 스택'으로 관리.
2023.12.08 - [JavaScript/모던 자바스크립트 Deep Dive] - 실행 컨텍스트 스택
'JavaScript > 모던 자바스크립트 Deep Dive' 카테고리의 다른 글
실행 컨텍스트 스택 (1) | 2023.12.08 |
---|---|
10장 - 2. 객체 리터럴 (프로퍼티 / 메서드) (0) | 2022.02.02 |
10장 - 1. 객체 리터럴 (객체 / 객체 리터럴) (0) | 2022.02.01 |
1장. 프로그래밍 (0) | 2021.11.02 |