코드의 실행환경에 대한 여러가지 정보를 담고 있는 개념 으로, 간단히 말하자면 자바스크립트 엔진에 의해 만들어지고 사용되는 코드 정보를 담은 객체의 집합이라고 할 수 있다.
(코드가 실행된다면 Execution Context 내부에서 실행되고 있는 것이다.)
엔진이 스크립트 파일을 실행하기 전에 글로벌 실행 컨텍스트(Global Execution Context, GEC) 가 생성되고, 함수를 호출할 때마다 함수 실행 컨텍스트(Function Execution Context, FEC) 가 생성된다. 글로벌의 경우 실행 이전에 생성되지만 함수의 경우 호출할 때 생성된다.
실행 컨텍스트는 다음과 같은 구성요소를 갖는다.
Lexical Environment: 현재 컨텍스트 내의 식별자들에 대한 정보 + 외부 참조 정보.
선언 시점의 LexicalEnvironment의 스냅샷으로, 변경 사항은 반영되지 않음
Variable Environment: : 처음에는 VariableEnvironment와 같지만 변경 사항이 실시간으로 반영됨
this 바인딩: this 식별자가 바라봐야 할 대상 객체
2개의 구성요소를 갖는다. Environment Record , outer 참조
Environment Record는 식별자에 관한 정보를 가지고 있으며,
outer 참조는 외부 Lexical Environment를 참조하는 포인터이다.
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를 찾아보는 방식이다.
현재 컨텍스트 내의 식별자들에 대한 정보 + 외부 환경 정보를 담는다.
선언 시점의 LexicalEnvironment의 스냅샵으로 변경 사항은 반영되지 않는다.
실행 컨텍스트를 생성할 때 variableEnvironment에 정보를 먼저 담은 다음,
이를 복사해서 LexicalEnvironment를 만든다.
(LexicalEnvironment(어휘적 환경): 처음에는 variableEnvironment와 같지만 변경 사항이
실시간으로 반영된다.)
this의 바인딩은 실행 컨텍스트가 생성될 때마다 this 객체에 어떻게 바인딩이 되는지를 나타낸 것이다.
GEC의 경우
FEC의 경우
실행컨텍스트는 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 {
ThisBinding: window,
LexicalEnvironment: {
EnvironmentRecord: {
b: <uninitialized>,
func: func(){...}
},
outer 참조: null
},
VariableEnvironment: {
EnvironmentRecord: {
a: undefined,
r: undefined
},
outer 참조: null
}
}
GEC {
ThisBinding: window,
LexicalEnvironment: {
EnvironmentRecord: {
b: 4,
func: func(){...}
},
outer 참조: null
},
VariableEnvironment: {
EnvironmentRecord: {
a: 3,
r: undefined
},
outer 참조: null
}
}
이제 func() 을 호출하고 FEC를 생성한다.
FEC {
ThisBinding: window,
LexicalEnvironment: {
EnvironmentRecord: {
arguments: { num: 4, length: 1 },
},
outer: GEC의 LexicalEnvironment
},
VariableEnvironment: {
EnvironmentRecord: {
t: undefined
},
outer: GEC의 LexicalEnvironment
}
}
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가 스택에서 제거된 뒤 프로그램이 종료된다.
실행 컨텍스트란, 코드를 실행하기 위해 필요한 정보들을 가진 범위를 객체 형태로 나타낸 것이다.
실행 컨텍스트를 구성하는 LexicalEnvironment는 현재의 실행 컨텍스트가 실행되기 위한 여러 정보를 담고 있다.
LexicalEnvironment는 식별자들에 대한 정보를 담은 EnvironmentRecord와, 상위 LexicalEnvironment를 참조해 스코프 체인을 가능하게 하는 OuterEnvironmentReference 정보로 구성되어 있다.
EnvironmentRecord는 식별자 바인딩을 관리하고, binding object라 불리는 특정 객체의 속성으로 선언된 식별자들을 관리한다.
OuterEnvironmentReference는 현재의 실행 컨텍스트를 구성한 함수가 선언되는 시점에서의 상위 LexicalEnvironment를 참조하기 때문에 식별자의 유효 범위를 상위로 거슬러 올라가 찾게 되는 스코프 체인이 가능하다.