자바스크립트 코드가 실행되고 연산되는 범위를 나타내는 추상적인 개념
- 자바스크립트 엔진은 script요소를 처음 만나는 시점에서 전역 실행 컨텍스트를 생성하고 Stack에 push한다
- 엔진이 함수 호출을 찾으면 해당 함수에 대한 함수 실행 컨텍스트를 생성해 Stack의 맨 위로 푸시한다.
- 엔진은 실행 컨텍스트가 Stack의 가장 맨 위 함수를 실행한 뒤 함수 종료시 Stack에서 제거하고 이를 반복한다.
실행 컨텍스트는
Creation Phase
와Execution Phase
의 두 단계로 생성된다
생성 단계에서는 두 가지 일이 일어난다
1. Lexical Environment 구성 요소 생성
2. Variable Environment 구성 요소 생성ExecutionContext ={ LexicalEnvironment = <ref. to LexicalEnvironment in memory>, VariableEnvironment = <ref. to VariableEnvironment in memory>, }
1.1 Lexical Environment
- 변수와 해당 변수에 대입된 값이 매핑되는 곳 1. Environment Records - 함수와 변수 선언을 저장하는 곳 2. Reference to the outer environment - 현재 Lexical Environment에서 변수를 찾지 못하면 외부 환겨에서 해당 변수를 찾아 볼 수 있다 3. This binding - 전역 실행 컨텍스트에서 this는 전역객체 - 함수 실행 컨텍스트에서 this는 함수가 객체 잠조에 의해 호출되면 해당 객체가 this, 아니라면 전역객체(window)를 가리킨다.
1.2 Variable Environment
- Variable Environment에서는 변수 var만 저장하고 Lexical Environment에서는 변수 let과 const바인딩을 가진다
let a = 20;
const b = 30;
var c;
function multiply(e, f) {
var g = 20;
return e * f * g;
}
c = multiply(20, 30);
GlobalExectionContext = { LexicalEnvironment: { EnvironmentRecord: { Type: "Object", // Identifier bindings go here a: < uninitialized >, b: < uninitialized >, multiply: < func > } outer: <null>, ThisBinding: <Global Object> }, VariableEnvironment: { EnvironmentRecord: { Type: "Object", // Identifier bindings go here c: undefined, } outer: <null>, ThisBinding: <Global Object> } }
GlobalExectionContext = { LexicalEnvironment: { EnvironmentRecord: { Type: "Object", // Identifier bindings go here a: 20, b: 30, multiply: < func > } outer: <null>, ThisBinding: <Global Object> }, VariableEnvironment: { EnvironmentRecord: { Type: "Object", // Identifier bindings go here c: undefined, } outer: <null>, ThisBinding: <Global Object> } }
FunctionExectionContext = { LexicalEnvironment: { EnvironmentRecord: { Type: "Declarative", // Identifier bindings go here Arguments: {0: 20, 1: 30, length: 2}, }, outer: <GlobalLexicalEnvironment>, ThisBinding: <Global Object or undefined>, }, VariableEnvironment: { EnvironmentRecord: { Type: "Declarative", // Identifier bindings go here g: undefined }, outer: <GlobalLexicalEnvironment>, ThisBinding: <Global Object or undefined> } }
FunctionExectionContext = {
LexicalEnvironment: {
EnvironmentRecord: {
Type: "Declarative",
// Identifier bindings go here
Arguments: {0: 20, 1: 30, length: 2},
},
outer: <GlobalLexicalEnvironment>,
ThisBinding: <Global Object or undefined>,
},
VariableEnvironment: {
EnvironmentRecord: {
Type: "Declarative",
// Identifier bindings go here
g: 20
},
outer: <GlobalLexicalEnvironment>,
ThisBinding: <Global Object or undefined>
}
}
호이스팅
- 앞서 본 예시코드 처럼, 생성단계에서 변수 및 함수 선언을 스캔하고 선언이 저장되며, 처음엔 초기화 되지 않은 상태로 설정된다.
- 이렇게 코드 실행 전 변수 선언이 먼저 메모리에 저장되어 선언 부분이 최상단으로 끌어올려지는 것처럼 보이는 것이 호이스팅이다.
실행 컨텍스트의 경우 모던 자바스크립트 책을 통해서도 공부를 해봤고, 유튜브나 인터넷을 통해서도 가끔 다시 복습을 하는 개념이다. 그만큼 자바스크립트로 개발을 할 때 중요한 개념이란것을 알기 때문에.. 가끔 자바스크립트로 개발을 하다보면 예상치 못한 에러를 (자주)마주하게 되는데..보통 이런 자바스크립트의 동작 원리에 대한 이해도가 부족해서 그런 것 같다! 열심히 공부해야지