Mistrie's story

Execution context 본문

개발/javascript

Execution context

Mistrie 2021. 1. 16. 16:17

* 분명히 정리해둔다고 해둔 거 같은데, 막상 살펴보니 정리해둔 게 없어서 정리함.

* 이 내용은 ES3 를 기반으로 하며, ES5부터는 lexical environment로 변경되었고, ES6 들어서도 내용이 좀 변화함
  그러나 기본적인 본질은 비슷하기에, execution context 에 대해서만 정리하려고 함.

 

 

1. Execution context 란?

* 쉽게 말해 JS 엔진에서 함수를 어떤 식으로 읽어들여서 수행할 것인지에 대한 정보들을 담고 있는 것이라 할 수 있음

* 예를 들어, foo 라는 함수를 호출했을 때, js 엔진에서는 foo에 대한 여러 정보들을 알고 있어야 실행할 수 있음

* 일반적으로 추상화된 개념이라고는 하지만, 내부적으로는 객체 형태로 정보들을 담고 있다고 함.

* Execution context 는 수행 시 execution context stack이라는 스택에 쌓이며 내용이 처리됨.

* 함수가 호출 되었을 때, 함수에 대한 execution context 가 생성되며, execution context stack에 쌓이고
  제어권이 넘어가게 됨.

* 그리고 실행이 종료되었을 때, 스택에서 소멸되며 다시 제어권이 자신의 함수 바로 이전에 호출한 함수로

  넘어가게 됨.

Execution context stack

 

2. Execution context 의 구조

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 정보를

  추가로 담고 있음

Global Execution context 의 GO
foo() execution context - AO

Scope Chain

* Scope chain 은 리스트 형태를 가지고 있으며, 자신과 자신의 상위에 대한 VO의 주소를 담고 있음

* 리스트의 제일 마지막은 전역 객체인 GO에 대한 주소를 담고 있음

* 이를 통해 자신에게 없는 변수는 scope chain을 통해 자신의 상위 VO에서 변수를 검색하며, 최종적으로는

  GO에서 변수를 검색하고 없으면 에러를 발생시킴

* 변수를 찾는 메커니즘은 scope chain에 의해서 이루어진다고도 볼 수 있음.

* 여기서 주의해야 할 점은 객체의 property를 찾는 것은 아님. 객체의 property 를 찾는 메커니즘은 정확히는

  prototype chain에 의해서 검색하게 됨.

Scope chain

 

this value

* this 값이 할당됨

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

 

this value

 

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 단계가 따로 이루어지므로, 변수 선언 이전에 참조하면 에러를 발생시킴.

       

let 의 변수 선언 이전 참조

* 여기서 중요한 포인트, 함수 객체(위 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