실행 컨텍스트(execution context)는 실행할 코드에 제공할 환경 정보들을 모아놓은 객체이다. 이는 자바스크립트의 동적 언어로서의 성격을 가장 잘 파악할 수 있는 개념이자, 가장 중요한 핵심 개념 중 하나이다.
- 실행 컨텍스트란?
- VariableEnvironment
- LexicalEnvironment
- this
1. 실행 컨텍스트란?
스택(stack)과 큐(queue)
- 스택은 출입구가 하나뿐이 깊은 우물 같은 데이터 구조.
저장한 순서의 반대로 꺼낼 수 밖에 없다. - 큐는 양쪽이 모두 열려있는 파이프 같은 구조.
보통은 한쪽은 입력만, 다른 한쪽은 출력만을 담당하는 구조.
저장한 순서대로 꺼낼 수 밖에 없다.
실행 컨텍스트
동일한 환경에 있는 코드들을 실행할 때 필요한 환경 정보를 모아 컨텍스트를 구성하고, 이를 콜 스택(call stack)에 쌓아올렸다가, 가장 위에 쌓여있는 컨텍스트와 관련 있는 코드들을 실행하는 식으로 전체 코드의 환경과 순서를 보장한다.
동일한 환경, 즉 하나의 실행 컨텍스트를 구성할 수 있는 방법으로 전역공간, eval() 함수, 함수 등이 있다.
[실행 컨텍스트와 콜 스택]
// -----(1)
var a = 1;
function outer() {
function inner() {
console.log(a); // undefined
var a = 3;
}
inner(); // -----(2)
console.log(a); // 1
}
outer(); // -----(3)
console.log(a); // 1
처음 자바스크립트 코드를 실행하는 순간 (1) 전역 컨텍스트가 콜 스택에 담긴다.
전역 컨텍스트와 관련된 코드들을 순차로 진행하다가 (3)에서 outer 함수를 호출하면 자바스트립트 엔진은 outer에 대한 환경 정보를 수집해서 outer 실행 컨텍스트를 생성한 후 콜스텍에 담는다.
콜 스택의 맨 위에 outer 실행 컨텍스트가 놓인 상태가 됐으므로 전역 컨택스트와 관련된 코드의 실행을 일시 중단하고 대신 outer 실행 컨텍스트와 관련된 코드, 즉 outer 함수 내부의 코드들을 순차로 실행.
다시 (2)에서 inner 함수의 실행 컨텍스트가 콜 스택의 가장 위에 담기면 outer 컨텍스트와 관련된 코드의 실행을 중단하고 inner 함수 내부의 코드를 순서대로 진행.
inner 함수 내부에서 a 변수의 값을 출력하고 나면 inner 실행 컨텍스트가 콜 스택에서 제거.
아래 있던 outer 컨택스트가 콜 스택의 맨 위에 존재하게 되므로 중단했던 (2)의 다음 줄 부터 이어서 실행.
a 변수의 값을 출력하고 나면 outer 함수의 실행이 종료되어 outer 실행 컨텍스트가 콜 스택에서 제거되고, 콜 스택에는 전역 컨텍스트만 남아있게 됨.
실행을 중단했던 (3)의 다음줄 부터 실행. a 변수의 값을 출력하고 나면 전역 공간에 더는 실행할 코드가 남아있지 않아 전역 컨텍스트도 제거되고, 콜 스택에는 아무것도 남지 않은 상태로 종료.
한 실행 컨텍스트가 콜 스택의 맨 위에 쌓이는 순간이 곧 현재 실행할 코드에 관여하게 되는 시점이다.
이렇게 어떤 실행 컨텍스트가 활성화될 때 자바스크립트 엔진은 해당 컨텍스트에 관련된 코드들을 실행하는데 필요한 환경 정보들을 수집해서 실행 컨텍스트 객체에 저장한다. (개발자가 코드로 확인할 수는 없음).
활성화된 실행 컨텍스트의 수집 정보
- VariableEnvironment: 현재 컨텍스트 내의 식별자들에 대한 정보 + 외부 환경정보. 선언 시점의 LexicalEnviornment의 스냅샷으로 변경 사항 반영되지 않음.
- LexicalEnvironment : 처음에는 VariableEnvioronment와 같지만, 변경 사항이 실시간으로 반영됨.
- ThisBinding: this 식별자가 바라봐야 할 대상 객체.
2. VariableEnvironment
VariableEnvironment에 담기는 내용은 LexicalEnvironment와 같지만 최초 실행 시의 스냅샷을 유지한다는 점이 다름.
실행 컨텍스트를 생성할 때 variableEnvironment에 정보를 먼저 담은 다음, 이를 그대로 복사해서 LexicalEnvironment를 만들고, 이후에는 LexicalEnvironment를 주로 활용하게 된다.
3. LexicalEnvironment
EnvironmentRecord와 호이스팅
EnvironmentRecord
- 현재 컨텍스트와 관련된 코드의 식별자 정보들이 저장.
- 전체 컨텍스트를 구성하는 함수에 지정된 매개변수 식별자, 선언한 함수가 있을 경우 그 함수 자체, var로 선언된 변수 식별자 등.
변수 정보를 수집하는 과정을 모두 마쳤더라도 아직 실행 컨텍스트가 관여할 코드는 실행되기 전의 상태.
자바스크립트 엔진은 식별자들을 최상단으로 끌어올려놓은 다음 실제 코드를 실행하는 것으로 간주할 수 있다.
호이스팅 규칙
//예제 1
function a(x) {
console.log(x) // (1)
var x;
console.log(x); // (2)
var x = 2;
console.log(x); // (3)
}
a(1);
// 매개변수를 변수 선언/ 할당과 같다고 간주해서 변환한 상태
function a() {
var x = 1;
console.log(x) // (1)
var x;
console.log(x); // (2)
var x = 2;
console.log(x); // (3)
}
a();
// 호이스팅을 마친 상태
function a() {
var x;
var x;
var x;
x = 1;
console.log(x) // (1)
console.log(x); // (2)
x = 2;
console.log(x); // (3)
}
a(1);
✔️ (1) 1, (2) 1, (3) 2가 출력됨
// 예제 2
function a() {
console.log(b); // (1)
var b = 'bbb';
console.log(b); // (2)
function b() {}
console.log(b); // (3)
}
a();
}
// 호이스팅을 마친 상태
function a() {
var b; // 변수는 선언부만 끌어올린다.
function b() {} // 함수는 전체를 끌어올린다.
console.log(b); // (1)
b = bbb; // 변수의 할당부는 원래 자리에 남겨둔다.
console.log(b); // (2)
console.log(b); // (3)
}
a();
✔️ (1) b함수, (2) 'bbb', (3) 'bbb'가 출력됨
함수 선언문(function declaration)과 함수 표현식(function expression)
- 둘 모두 함수를 새롭게 정의할 때 쓰이는 방식
- 함수 선언문은 function 정의부만 존재하고 별도의 할당 명령이 없음
- 함수 표현식은 정의한 function을 별도의 변수에 할당하는 것을 말함. 일반적으로 함수 표현식은 익명 함수 표현식을 말함.
function a () {} // 함수 선언문
a();
var b = function() {} // (익명)함수 표현식
b();
var c = function d () {} // 기명 함수 표현식 변수명: c 함수명: d
c(); // 실행 O
d(); // 에러!
기명 함수 표현식의 주의할 점
외부에서는 함수명으로 함수를 호출할 수 없으며 오직 함수 내부에서만 접근할 수 있다.
// 함수 선언문과 함수 표현식
console.log(sum(1,2));
console.log(multiply(3,4));
function sum(a, b) { // 함수 선언문 sum
return a + b;
}
var multiply = function (a, b) { // 함수 표현식 multiply
return a * b;
}
// 호이스팅을 마친 상태
var sum = function sum(a, b) { // 함수 선언문은 전체를 호이스팅
return a + b;
};
var multiply; // 변수는 선언부만 끌어올림
console.log(sum(1,2));
console.log(multiply(3,4));
multiply = function (a, b) {
return a * b;
};
상대적으로 함수 표현식이 안전하다.
원활한 협업을 위해서는 전역공간에 함수를 선언하거나 동명의 함수를 중복 선언 하는 경우는 없어야 한다.
스코프, 스코프 체인, outerEnvironmentReference
- 스코프(scope): 식별자에 대한 유효범위
- 스코프 체인(scope chain) 식별자의 유효범위를 안에서부터 바깥으로 차례로 검색해나가는 것
outerEnvironmentReference는 현재 호출된 함수가 선언될 당시의 LexicalEnvironment를 참조한다.
4. this
this에는 실행 컨텍스트를 활성화하는 당시에 지정된 this가 저장됨.
함수를 호출하는 방법에 따라 그 값이 달라지는데, 지정되지 않은 경우에는 전역 객체가 저장된다.
'아카이브 > JavaScript' 카테고리의 다른 글
[코어 자바스크립트] 06 프로토타입 (0) | 2021.12.07 |
---|---|
[코어 자바스크립트] 05 클로저 (0) | 2021.12.06 |
[코어 자바스크립트] 04 콜백함수 (0) | 2021.12.05 |
[코어 자바스크립트] 03 this (0) | 2021.12.04 |
[코어 자바스크립트] 01 데이터 타입 (0) | 2021.11.29 |