Execution Context 란?
스코프와 코드 실행 순서를 관리하는 자바스크립트 내부 수행 매커니즘이다.
var a = 3;
function f() {
var b = 7;
console.log(a + b); // 10
}
f();
console.log(a); // 3
코드에서 변수 b는 f함수 내에서 유효하며, a는 f함수를 포함한 코드 전체에서 유효하다.
이처럼 어떤 식별자가 유효한 범위를 스코프라 한다. 스코프는 lexical environment을 통해 관리한다.
코드 실행 순서는 아래와 같다.
1. a에 3을 대입한다.
2. f 함수로 실행 흐름이 넘어간다.
3. b에 7을 대입한다.
4. a + b를 출력한다.
5. 전역 코드로 다시 실행 흐름이 넘어온다.
6. a를 출력한다.
이와 같은 코드 실행 흐름은 execution context stack(call stack)을 통해 관리한다.
자바스크립트 프로그램 실행 과정
자바스크립트 프로그램 실행 과정은 코드를 평가하는 단계와 코드를 순차적으로 실행하는 런타임으로 나뉜다.
1. 코드 평가 시에는 execution context를 생성하고, 선언문만 실행하면서 변수나 함수 등 식별자를 lexical environment에 등록한다.
2. 런타임에는 필요한 정보를 lexical environment에서 가져오고, 실행 결과를 등록한다.
프로그램 실행 과정 예시
예시를 통해 어떻게 execution context가 생성되고, 스코프와 실행 순서가 관리되는지 알아보겠다.
var x = 3;
function foo() {
var x = 10;
function bar() {
var x = 7;
console.log(x);
}
bar();
console.log(x);
}
foo();
console.log(x);
위 프로그램을 실행하면
1. 자바스크립트 엔진은 가장 먼저 전역 코드를 평가 과정을 시작한다.
1-1. 먼저 global execution context를 생성하고 execution context stack에 푸시한다.
1-2. Global lexical environment를 생성하고 global execution context에 바인딩한다.
1-3. 선언문을 읽으며 식별자를 등록한다. OuterLexicalEnvironmentReference는 상위 스코프에 대한 참조인데, 현재 전역 코드로 상위 스코프가 없으므로 null이다. Lexical Environment는 실제로 아래와 같은 구성은 아니지만, 단순하게 표현했다.
2. 전역 코드 평가가 종료되어 코드를 순차적으로 실행한다.
2-1. x = 3; 수행 결과로 x에 값 3이 등록되었다.
2-2. 전역 코드 실행 중 foo() 함수가 호출되었다. 실행 중에 함수가 호출되면, 현재 실행 흐름을 멈추고 호출된 함수에 대한 평가 및 실행 과정이 시작된다.
3. foo 함수 평가 과정을 시작한다.
3-1. 전역 코드와 같이, foo 함수의 execution context를 stack에 추가하고, lexical environment를 바인딩한다.
3-2. 선언문을 읽으며 변수 x와 함수 bar를 lexical environment에 등록한다. OuterLexicalEnvironmentReference는 global lexical environment를 참조한다. 이렇게 단방향 리스트로 lexical environment가 연결되어진 것이 스코프 체인이다.
4. foo 함수를 실행한다.
4-1. x 변수의 값으로 10을 등록한다.
4-2. bar 함수가 호출되어 bar함수의 평가 및 실행 과정을 시작한다.
5. bar 함수를 평가한다. bar의 execution context를 stack에 push, lexical environment와 바인딩, 변수 x를 등록한다. OuterLexicalEnvironmentReference는 foo함수의 lexical environment를 참조한다.
6. bar 함수를 실행한다.
6-1. 변수 x에 7을 등록한다.
6-2. 변수 x를 출력한다.
7. bar 함수 실행이 끝나 stack에서 bar executoin context를 pop한다. 이때, bar 함수의 lexical environment까지 즉시 없어지는 것은 아니다. Lexical environment를 참조하는 값이 없어지면 가비지 컬렉터에 의해 메모리가 반환된다.
8. foo 함수에서 x를 출력한다.
9. foo execution context를 pop한다.
10. 전역 코드에서 x를 출력하고, global execution context를 pop한다.
지금까지 자바스크립트 엔진이 코드를 실행하는 과정이었다. 예시에서는 항상 같은 스코프에 존재하는 변수 x를 활용했지만, 아래 코드와 같이 상위 스코프의 변수를 활용하는 경우도 있다.
var a = 3;
function f() {
var b = 5;
console.log(a + b); // 상위 스코프의 변수 a 활용
}
f();
이때는 lexical environment의 OuterLexicalEnvironmentReference를 통해, 상위 스코프로 올라가며 필요한 변수에 접근한다.
자바스크립트는 let, const는 블록 레벨 스코프를 따른다. 아래와 같은 코드에서 if 블록 코드를 실행할 때는, if 코드 블록에 대한 lexical environment가 생성되고, execution context가 그를 가리킨다.
let a = 3;
if (a === 3) {
let b = 5;
}
if 문이 종료되면 execution context는 다시 이전의 lexical environment를 가리킨다.
'JAVASCRIPT' 카테고리의 다른 글
DOM과 Virtual DOM (0) | 2022.01.16 |
---|---|
자바스크립트 Promise (0) | 2022.01.14 |
자바스크립트 가비지 콜렉션과 순환참조 (0) | 2021.12.10 |
자바스크립트 변수 호이스팅 (0) | 2021.12.04 |
JavaScript Closure (0) | 2021.04.21 |