웹공부

실행 컨텍스트 (Execution Context)

syom 2022. 4. 21. 09:36

정의

자바스크립트가 실행될 때 필요한 변수, 스코프의 정의, this 값 등이 정의되는 환경

종류

  • GEC (Global execution context)
    • JS가 실행될때 맨 처음에 시작되는 실행 컨텍스트
    • JS 는 싱글 스레드이기 때문에 무조건 하나만 존재함
  • FEC (Functional execution context)
    • 실행 컨텍스트는 함수마다 생길 수 있음
    • 함수가 호출되고 실행될 때 만들어지는 실행 컨텍스트
  • Eval
    • eval 함수가 실행될 때 만들어지는 실행 컨텍스트

execution context stack

  • 콜스택과 비슷한 구조

실행 컨텍스트 생성 과정

  1. Creation Phase
    • Create the Activation object / Variable Object
      • Activation object : 글로벌 실행 컨텍스트의 variable object
    • Create the scope chain
      • scope chain : 스코프(변수가 유효한 범위)가 체인처럼 묶여있는 것
    • Determines the value of this
      • this의 값을 결정
  2. Execution Phase
    • 변수 등에 할당

예제

다음과 같은 js 코드가 있다고 가정해보자.

a = 1;
var b = 2;

cFunc = function(d) {
	var e = 3;
	var f = 4;

	a = 5;

	function dFunc() {
		var g = 1;
	}
	dFunc();
}

cFunc();

맨 먼저 전역 스코프의 Creation Phase 가 실행된다.

이 과정에서 변수 선언이 저장되고, scope chain, this 값들이 저장된다.

const GlobalExecutionContextObj = {
	activationObj: {
		argumentsObj : {
			length: 0
		},
		b: undefined,
		cFunc: Pointer to the function definition.
	},
	scopeChain: [Global execution context variable object],
	this: value of this
}

전역 스코프의 Creation Phase가 실행되어 activation object 가 생성되고 나면 바로 전역스코프의 Execution Phase 로 넘어가 코드를 한줄 한줄 실행하게 된다.

  • a와 같은 경우는 전역 스코프에서 새로 변수로 선언되는 것이 아니기 때문에 이 과정에서 저장되지 않는다.

( 이 실행 컨텍스트가 전역이 아닌 함수 스코프 내의 실행 컨텍스트라 생각한다면 a = 1 자체가 기존에 저장된 변수의 값을 바꾸는 걸 수도 있다. 스코프 체이닝을 통하여 상위 스코프에 해당 변수가 있는지 체크하고 있다면 그 스코프에 저장하는 방식으로 바뀌게 된다고 이해하면 좋을 것 같다. 만약 전역스코프에서 적혀있다면 Creation Phase 가 아닌 Execution Phase 에서 값이 저장된다. )

  • function의 경우는 이 과정에서 선언을 만났을 때 힙 메모리에 저장 되고 그 주소값을 저장한다.

Execution Phase 에선 변수에 할당이 이루어진다.

a = 1;
var b = 2;

cFunc = function(d) {
	var e = 3;
	var f = 4;

	a = 5;

	function dFunc() {
		var g = 1;
	}
	dFunc();
}
// <---
cFunc(10); 

화살표의 지점에 왔을 때 전역 스코프의 실행 컨텍스트는 아래와 같을 것이다.

const GlobalExecutionContextObj = {
	activationObj: {
		argumentsObj : {
			length: 0
		},
		a: 1,
		b: 2,
		cFunc: Pointer to the function definition.
	},
	scopeChain: [Global execution context variable object],
	this: value of this
}

a의 값이 새로 추가되고 b의 값이 undefined가 아닌 2 로 할당되었을 것이다.

그리고 화살표의 아랫줄인 cFunc(10); 를 실행시키는 순간 cFunc 에 대한 새로운 실행 컨텍스트가 만들어지게 된다. (= cFunc의 Creation Phase 가 시작된다)

const cFuncExecutionContextObj = {
	variationObj: {
		argumentsObj : {
			1: d,
			length: 1
		},
		d: 10,
		e: undefined,
		f: undefined,
		dFunc: Pointer to the function definition.
	},
	scopeChain: [cFunc variation object, Global execution context variable object],
	this: value of this
}

cFunc의 creation phase 가 실행되고 난 뒤의 cFunc 실행 컨텍스트의 상태는 위와 같을 것이다.

  • argumentsObj 의 경우, 인자로 d 를 받는데 cFunc를 실행할 때에 10을 인자로 넘겼기 때문에 creation phase 단계에서 d 가 10으로 저장된다.
  • scopeChain 의 경우, 아까 전역 실행 컨텍스트에서는 단순히 전역임을 나타내는 것만 있었다면 cFunc 에서는 전역 실행 컨텍스트를 history 마냥 배열로 저장이 되는 것을 알 수 있다.

이후 과정은 비슷하게 진행될 것이라 생략한다.

Closure

실행 컨텍스트가 만들어질 때 스코프 체인의 생성과 초기화도 일어나는데, 이는 함수 내에 [[Scopes]] 로 저장된다.

참조하고 있는 값이 있다면 이 [[Scope]] 내에 Closure 로 저장이 되기 때문에 실행 컨텍스트 자체가 종료되어 접근이 안되더라도 저장되어 있어 가비지 컬렉터가 이를 회수할 수 없게 되므로 참조할 수 있다. 이를 Closure 라고 한다.

 

출처 강의 : https://www.youtube.com/channel/UCY4W_6R3mnN8LDr3IjQOhFw