정의
코드의 실행환경에 대한 여러가지 정보를 가진 개념 으로, 간단하게 자바스크립트 엔지에 의해 만들어지고 사용되는 코드 정보를 담은 객체 집합이다.
종류
JS 코드는 3가지 종류가 있다.
글로벌 스코프에서 실행되는 글로벌 코드, 함수 스코프에서 실행되는 함수코드, 그리고 이 글에서 다루지 않는 eval()로 실행되는 코드가 있다.(eval()와 관련된 렉시컬 스코프에 대해서는 다음 글에서 정리 하겠다.)
각각의 코드는 자신만의 실행 컨텍스트를 생성한다.
엔진이 스크립트 파일을 실행하기 전, 글로벌 실행 컨텍스트(Global Execution Context, GEC)가 생성되고, 함수를 호출할 때마다 함수 실행 컨텍스트(Function Execution Context, FEC)가 생성된다.
주의할 점은 글로벌의 경우 실행 이전에 생성되지만 함수의 경우 호출할 때 생성된다는 점이다.
실행 컨텍스트 스택
실행 컨텍스트가 생성되면 콜 스택(Call Stack)이라고도 불리는 실행 컨텍스트 스택에 쌓이게 된다.
GEC는 코드를 실행하기 전에 쌓이고 모든 코드를 실행하면 제거된다.
FEC는 호출할 때 쌓이고 호출이 끝나면 제거된다.
const func = () => {
console.log('함수 실행 컨텍스트');
}
console.log('글로벌 실행 컨텍스트');
func();
처음으로, 코드를 실행하기 전에 GEC가 쌓기오 코드를 실행하면 콘솔에 "글로벌 실행 컨텍스트" 가 출력된다.
그 다음 func()를 호출하게 되면 FEC가 만들어지고 FEC가 실행하며 콘솔에 "함수 실행 컨텍스트" 가 출력된다.
이후, func()가 종료되고 FEC가 스택에서 제거된 후, 모든 실행 컨텍스트가 끝나면서 GEC가 스택에서 제거된다.
구성요소
실행 컨텍스트는 3가지 구성요소를 갖는다.
- Lexical Environment (렉시컬 환경)
- Variable Environment (변수 환경)
- this 바인딩
Lexical Environment(렉시컬 환경)
변수 및 함수 등의 식별자(Identifier) 및 외부 참조에 관한 정보를 가지고 있는 컴포넌트이다.
이 컴포넌트는 2개의 구성요소로 이루어져 있다.
- Environment Record
- outer 참조
Environment Record는 식별자들의 바인딩을 기록하는 객체이며 변수, 함수 등이 기록되는 곳이다.
outer 참조는 외부 렉시컬 환경을 참조하는 포인터이다.
var x = 10;
function foo() {
var y = 20;
console.log(x);
}
위의 코드가 있을 때는 아래와 같이 Lexical Environment가 형성된다.
globalEnvironment = {
environmentRecord = { x: 10 },
outer: null
}
fooEnvironment = {
environmentRecord = { y: 20 },
outer: globalEnvironment
}
따라서, foo()에서 x를 참조할 때는 현재 Environment Record를 찾아보고 없기 때문에 outer를 참조를 사용해 외부의 Lexical Environment에 속해 있는 Environment Record를 찾아보는 방식이다.
Variable Environment(변수 환경)
Variable Environment는 렉시컬 환경과 동일한 성격을 띄지만, var로 선언된 변수만 저장한다는 점에서 다르다.
즉, 렉시컬 환경은 var로 선언된 변수를 제외하고 나머지를 저장한다. (ex. let, const 등 )
this 바인딩
this의 바인딩은 실행 컨텍스트가 생성될 때마다 this 객체에 어떻게 바인딩이 되는지를 나타낸 것이다.
(ES6부터 this바인딩이 Lexical Environment 안에 있는 Environment Record 안에서 일어남)
- GEC의 경우
- strict mode라면 undefined로 바인딩 된다.
- 아니라면 글로벌 객체로 바인딩 된다.(브라우저에서는 window, 노드에서는 global)
- FEC의 경우
- 해당 함수가 어떻게 호출되었는지에 따라 바인딩 된다.
과정
EC는 2가지 과정을 거친다.
- Creation Phase (생성 단계)
- Execution Phase (실행 단계)
생성 단계
생성 단계는 3가지로 이루어진다.
- Lexical Environment 생성
- Variable Environment 생성
- this 바인딩
여기서 주의할 점은 값이 변수에 매핑되지 않는다.
var의 경우는 undefined로 초기화되고 let이나 const는 값도 가지지 않는다.
실행 단계
코드를 실행하면서 변수에 값을 매핑시킨다. 예시를 보자
var a = 3;
let b = 4;
function func(num) {
var t = 9;
console.log(a + b + num + t);
}
var r = func(4);
GEC의 생성 단계
여기서 생성이 될 때 실행 컨텍스트 스택에 쌓인다.
GEC {
ThisBinding: window,
LexicalEnvironment: {
EnvironmentRecord: {
b: <uninitialized>,
func: func(){...}
},
outer 참조: null
},
VariableEnvironment: {
EnvironmentRecord: {
a: undefined,
r: undefined
},
outer 참조: null
}
}
GEC의 실행 단계
GEC {
ThisBinding: window,
LexicalEnvironment: {
EnvironmentRecord: {
b: 4,
func: func(){...}
},
outer 참조: null
},
VariableEnvironment: {
EnvironmentRecord: {
a: 3,
r: undefined
},
outer 참조: null
}
}
FEC의 실행 단계
FEC {
ThisBinding: window,
LexicalEnvironment: {
EnvironmentRecord: {
arguments: { num: 4, length: 1 },
},
outer: GEC의 LexicalEnvironment
},
VariableEnvironment: {
EnvironmentRecord: {
t: 9
},
outer: GEC의 LexicalEnvironment
}
}
FEC가 스택에서 제거 되고 GEC의 r이 20으로 초기화된다.
GEC {
ThisBinding: window,
LexicalEnvironment: {
EnvironmentRecord: {
b: 4,
func: func(){...}
},
outer 참조: null
},
VariableEnvironment: {
EnvironmentRecord: {
a: 3,
r: 20
},
outer 참조: null
}
}
모든 코드를 실행하고 GEC가 스택에서 제거된 뒤 프로그램이 종료된다.
위에 있는 GIF를 보면 더 확실히 이해할 수 있다.
'JavaScript > Javascript' 카테고리의 다른 글
this 바인딩 (0) | 2023.09.22 |
---|---|
호이스팅 (0) | 2023.09.21 |
스코프 (0) | 2023.09.21 |
이벤트 위임 (0) | 2023.09.18 |
AJAX (0) | 2023.09.11 |