Mistrie's story
Execution context 본문
* 분명히 정리해둔다고 해둔 거 같은데, 막상 살펴보니 정리해둔 게 없어서 정리함.
* 이 내용은 ES3 를 기반으로 하며, ES5부터는 lexical environment로 변경되었고, ES6 들어서도 내용이 좀 변화함
그러나 기본적인 본질은 비슷하기에, execution context 에 대해서만 정리하려고 함.
1. Execution context 란?
* 쉽게 말해 JS 엔진에서 함수를 어떤 식으로 읽어들여서 수행할 것인지에 대한 정보들을 담고 있는 것이라 할 수 있음
* 예를 들어, foo 라는 함수를 호출했을 때, js 엔진에서는 foo에 대한 여러 정보들을 알고 있어야 실행할 수 있음
* 일반적으로 추상화된 개념이라고는 하지만, 내부적으로는 객체 형태로 정보들을 담고 있다고 함.
* Execution context 는 수행 시 execution context stack이라는 스택에 쌓이며 내용이 처리됨.
* 함수가 호출 되었을 때, 함수에 대한 execution context 가 생성되며, execution context stack에 쌓이고
제어권이 넘어가게 됨.
* 그리고 실행이 종료되었을 때, 스택에서 소멸되며 다시 제어권이 자신의 함수 바로 이전에 호출한 함수로
넘어가게 됨.

2. Execution context 의 구조

* Execution context 는 크게 3가지 정보를 담고 있음
* 첫번째로는 변수와 내부 함수들의 정보(매개변수, 인수 정보 등)
* 두번째로는 변수의 유효 범위(scope)
* 마지막으로는 this 바인딩 정보를 담고 있음
* 이런 정보들은 위의 그림과 같이 Variable Object, Scope chain, thisValue를 통해 값을 담고 있음
Variable Object
* Variable Object(줄여서 VO)는 변수들에 대한 정보, 내부 함수 객체에 대한 정보 등을 담고 있는 객체를
가리킴.
* 이러한 정보를 담고 있는 객체는 전역 코드를 수행할 때와 일반 함수 호출에 의해 함수에 대한
execution context를 생성했을 때 명칭이 약간 다름
* 전역 코드를 수행하려고 execution context를 생성하면, 이때 변수 정보들과 함수 객체 정보들을 담고 있는 객체를
Global Object(줄여서 GO)라고 부름
* 일반 함수를 호출했을 때에는 Activation Object(줄여서 AO)라고 부름
* GO와 AO는 거의 같으나, AO 같은 경우 함수 호출에 의해 생성되었으므로 매개변수와 arguments 정보를
추가로 담고 있음


Scope Chain
* Scope chain 은 리스트 형태를 가지고 있으며, 자신과 자신의 상위에 대한 VO의 주소를 담고 있음
* 리스트의 제일 마지막은 전역 객체인 GO에 대한 주소를 담고 있음
* 이를 통해 자신에게 없는 변수는 scope chain을 통해 자신의 상위 VO에서 변수를 검색하며, 최종적으로는
GO에서 변수를 검색하고 없으면 에러를 발생시킴
* 변수를 찾는 메커니즘은 scope chain에 의해서 이루어진다고도 볼 수 있음.
* 여기서 주의해야 할 점은 객체의 property를 찾는 것은 아님. 객체의 property 를 찾는 메커니즘은 정확히는
prototype chain에 의해서 검색하게 됨.

this value
* this 값이 할당됨
* 여기에서 this는 이전 포스팅에서 언급했듯이, 함수 호출 패턴에 의해 결정되며, 최초에는 GO를 가리킴

3. Execution context의 생성 과정
* 생성과정은 정말 길지만, 간단히 설명하겠음
* 우선 전역 코드로 돌입하기 전에, 유일한 전역 객체인 GO 가 생성됨
* 이후 Global EC 가 생성되고 execution context stack에 쌓임
* 이후 3가지 과정에 의해서 값을 채우는데, 이 순서는 항상 일정함.
- 1. Scope chain의 생성과 초기화
- 2. Variable Instantiation (변수 객체화) 실행 -> 변수의 선언, 초기화, 할당이 이루어짐
- 3. this value 결정
* 이때 변수 객체화는 아래의 순서로 실행하며, 반드시 순서대로 실행됨
- 1. (Function Code 인 경우) 매개변수가 AO의 프로퍼티로, argument 가 값으로 설정됨
- 2. 대상 코드 내의 함수 선언(함수 표현식 제외)을 대상으로 함수명이 property, 함수 객체가 값으로 설정됨
(이 과정이 함수 호이 스팅의 원리임!)
- 3. 대상 코드 내의 변수 선언을 대상으로 변수명이 GO / AO의 property, undefined 가 값으로 설정됨.
이 과정을 조금 더 세분화하면 3단계로 이루어짐.
3.1. 변수 선언 단계 - GO / AO에 변수가 등록됨
3.2. 변수 초기화 단계 - 변수 값을 메모리에 할당함. 이 단계에서 변수는 undefined로 초기화됨
3.3. 변수 할당 단계 - 실제 코드 수행에 돌입해서 해당 라인을 만나면, 실제 변수 값을 담음.
- 실제로 위 과정 중, 3.1, 3.2 가 한 번에 이루어짐. 따라서 변수 선언 이전에 변수에 접근해도 GO / AO에
변수가 등록되어 있기 때문에, 에러가 발생하지 않음
- 이러한 현상을 변수 호이 스팅이라고 함.
- 여담으로 ES6의 let 은 위 3.1, 3.2 단계가 따로 이루어지므로, 변수 선언 이전에 참조하면 에러를 발생시킴.

* 여기서 중요한 포인트, 함수 객체(위 EC 사진 중 foo ec에서 AO에 담고 있는 bar 함수)는 내부적으로
[[Scopes]]라는 내부 프로퍼티를 소유함
* 이 프로퍼티는 함수 객체가 실행되는 환경을 가리킴.
* 즉, 위 사진에서 foo의 [[Scopes]] 는 Global EC의 Scope chain 리스트를 가리키며,
bar의 [[Scopes]] 는 foo EC의 Scope chain을 가리킴.
* 이러한 원리로 인해 자신을 포함하는 외부 함수의 execution context 가 소멸하여도, [[Scopes]] 프로퍼티가 가리키는
외부 함수의 실행환경(AO)은 소멸하지 않고 참조할 수 있음.
* 이것이 바로 클로저임!
'개발 > javascript' 카테고리의 다른 글
| Event loop 에 대한 정리 (0) | 2021.01.05 |
|---|---|
| Function - 일급 객체 (0) | 2020.12.24 |
| JavaScript - Scope / this (0) | 2020.12.23 |
| JavaScript core - prototype chain (0) | 2020.12.23 |
| Javascript 1~5장 중요 부분 정리 (0) | 2013.07.18 |