소스코드 타입은 실행 컨텍스트를 생성하는 과정과 관리 내용이 다르기 때문에 ECMAScript 사양은 소스코드를 4가지 타입으로 구분한다.
소스코드 평가 과정에서는 1. 실행 컨텍스트를 생성
후 2. 선언문만 먼저 실행
해서 생성된 변수, 함수 식별자를 키로 하는 실행 3. 컨텍스트가 관리하는 스코프에 등록(렉시컬)
한다. 평가가 끝나면 런타임(실행 과정)
이 시작되며, 이때 선언문을 제외한 소스코드가 순차적으로 실행된다.소스코드 실행에 필요한 정보(변수, 함수 참조 등)는 실행 컨텍스트가 관리하는 스코프에서 취득한다. 식별자와 스코프는 렉시컬 환경, 코드 실행 순서는 실행 컨텍스트 스택으로 관리된다.
const a = 1; // 전역코드 평가(실행 컨텍스트 생성)
const b = 2; // 전역코드 평가
// 전역코드 평가
function foo(p) { // 함수 실행 컨텍스트 생성
const a = 10; // 함수 실행 컨텍스트 등록
const b = 20;
console.log(p + a + b); // 130
} // 함수 코드 평가 끝
foo(100); // 전역 코드 실행 일시 중단 & 함수 내부 진입
console.log(a + b); // 3
전역 코드 평가
• 전역 코드의 변수 선언문, 함수 선언문이 먼저 실행
• 결과로 생성된 전역 변수와 전역 함수가 실행 컨텍스트가 관리하는 전역 스코프에 등록
전역 코드 실행
• 전역 코드 평가 과정 이후 런타임을 시작하여 순차적으로 코드 실행
• 전역 변수에 값이 할당되고, 함수가 호출되는데 함수가 호출되면 전역 코드의 실행을 일시 중단하고 함수 내부 진입
함수 코드 평가
• 함수 내부로 진입하면 함수 코드 평가 과정을 거친다.
• 매개변수, 지역 변수 선언문 실행 후 결과로 생성된 매개변수, 지역 변수가 실행 컨텍스트가 관리하는 지역 스코프에 등록
• arguments 객체가 생성되며, this 바인딩도 결정된다.
함수 코드 실행
• 함수 코드가 순차적으로 실행되며, 매개변수와 지역 변수에 값이 할당되고 함수 내부 코드가 실행
• 코드가 실행되려면 스코프를 구분해서 식별자와 바인딩된 값이 관리되어야 한다.
• 스코프 체인으로 식별자 검색
• 전역 변수 프로퍼티 검색
• 실행 중 코드, 이전 코드 구분
스택(Stack)
이란, 자료구조 중 하나로 한 쪽 끝에서만 자료를 넣거나 뺄 수 있는 구조를 말한다. 가장 나중에 삽입한 자료를 가장 먼저 꺼내는 LIFO(Last in First Out)
구조로 구성되어 있다.
자료의 삽입을 Push, 자료를 꺼내는 것을 Pop이라 표현한다.
const x = 1;
function outer() {
const y = 2;
function inner() {
const z = 3;
console.log(x + y + z);
}
inner();
}
outer();
예시 코드의 실행 순서를 살펴보면 전역 실행 컨텍스트 - outer 함수 실행 컨텍스트 - inner 함수 실행 컨텍스트 순서대로 이뤄진다. 실행 컨텍스트는 스택 자료구조로 관리되기 때문에 가장 먼저 생성된 컨텍스트부터 순서대로 쌓이게 된다.
실행 컨텍스트 스택은 코드의 실행 순서를 관리하며 실행 컨텍스트 스택의 최상위에 존재하는 실행 컨텍스트는 언제나 현재 실행 중인 코드의 실행 컨텍스트다.
렉시컬 환경(Lexical Environment)
는 식별자, 식별자에 바인딩된 값, 상위 스코프에 대한 참조를 기록하는 자료구조이다. 렉시컬 환경은 객체 형태의 스코프를 생성하여, 식별자를 키로 등록하고 식별자에 바인딩된 값을 관리한다.
환경 레코드
는 스코프에 포함된 식별자를 등록하고, 식별자에 바인딩된 값을 관리하는 저장소다.
외부 렉시컬 환경에 대한 참조
는 상위 스코프를 가리키며, 해당 실행 컨텍스트를 생성한 소스코드를 포함하는 상위 코드의 렉시컬 환경을 의미한다.
// 렉시컬 환경
var x = 1;
const y = 2;
function outer(a) {
var x = 3;
const y = 4;
function inner(b) {
const z = 5;
console.log(a + b + x + y + z);
}
inner(10);
}
outer(20);