본문 바로가기

IT/javascript

[javascript] 실행 컨텍스트(Execution Context)

1. 실행 컨텍스트란?

자바스크립트 코드가 실행되고 있는 구역 또는 범위에 대한 정보를 저장하고 있는 객체입니다.

자바스크립트 엔진은 스크립트 혹은 함수를 실행할 때 새로운 컨텍스트를 만들고, 실행 스택에 쌓습니다. 

실행 스택이란 실행 컨텍스트가 생성될 때 마다 실행 컨텍스트를 쌓고 마지막으로 쌓인 실행 컨텍스트 부터 차례대로 실행하는 후입선출 자료구조입니다.

 

2. 실행 컨텍스트의 종류

1) Global Exception Context
자바스크립트 엔진이 실행될 때 가장 먼저 만드는 실행 컨텍스트입니다.
전역 컨텍스트라고 하며, window 객체를 만들고 전역 컨텍스트의 this를 window 객체로 할당합니다.

그리고 이후에 생성되는 모든 전역 변수, 함수는 window 객체에 저장됩니다.

2) Function Execution Context
함수가 호출되면, 함수의 실행 컨텍스트가 생성됩니다.

3) Eval Function Exception
사용되지 않음

 

실행 컨텍스트의 구조

ExecutionContext = {
    LexicalEnvironment : { 
    	EnvironmentRecords : {
           //function or variable
        },
        outer : (LexicalEnvironment),
        ThisBinding : (object)
    },
    
    VariableEnvironment : {(LexicalEnvironment와 동일한 구조)}
}

 

3. 실행 컨텍스트의 두가지 단계

모든 실행 컨텍스트는 Create 단계 Execution 단계를 통해 생성됩니다.

1) Create 단계

Create 단계에서 LexicalEnvironment 컴포넌트 VariableEnvironment 컴포넌트를 생성합니다.
두 컴포넌트가 생성될 때, VariableEnvironment 컴포넌트는 LexicalEnvironment 컴포넌트를 참조합니다.
그러다가 자바스크립트의 코드에 따라 참조가 바뀌기도 합니다.
executionContext.LexicalEnvironment = executionContext.VariableEnvironment;

 

 

1.1) LexicalEnvironment 

LexicalEnvironment 컴포넌트는 변수나 함수 등의 식별자를 저장하는 EnvironmentRecords 객체와 외부 LexicalEnvironment 컴포넌트를 참조하는 outer 그리고 this로 구성됩니다. 
outer는 스코프 탐색을 위해 사용됩니다.

LexicalEnvironment 컴포넌트는 3가지 동작을 합니다.

1) 변수와 함수의 저장공간을 메모리에 할당
실행 컨텍스트 내에서 선언된 변수와 함수의 저장공간을 메모리에 할당하고 EnvironmentRecords라는 객체에 저장합니다.

2) 외부 실행 컨텍스트의 LexicalEnvironment를 저장
코드를 실행하다가 특정 변수나 함수를 마주하면 LexicalEnviromemt에서 찾는데 찾지 못했을 경우 외부 LexicalEnvironment 에서 찾습니다. (scope chain)

3) 실핼 컨텍스트의 This 값을 지정
this 값은 이 단계에서 결정됩니다. 전역 실행 컨텍스트의 this 는 global object입니다. 

this 값은 함수를 호출한 객체를 가리키게 됩니다. 

 

this를 이해하기 위해 간단한 소스를 보겠습니다.

var player = {
    lastName : 'son',
    firstName : 'heung min',
    name : function(){
       console.log(`${this.lastName} ${this.firstName}`);
    }
}

player.name(); // son heung min

var getName = player.name;

getName(); // undefined undefined
// == window.getName()
player.name()은 player 객체가 호출했기 때문에 this값은 player 객체입니다.

getName()은 player.name 함수를 대입받았고, 그대로 실행 했기 때문에 this값은 window 객체를 가리킵니다.

 

정리하면 Create 단계에서는
1) 변수, 함수, 인자를 만들고 EnvronmentRecords에 저장합니다.
2) 외부 실행 컨텍스트를 가리킵니다. (Scope Chain)
3) 실행 컨텍스트 내에 선언된 변수와 함수를 찾아 메모리에 할당합니다. (호이스팅)
4) this가 결정됩니다.

2) Execution 단계

실행 컨텍스트 내에 코드들을 위에서 한줄 씩 읽으면서 선언해 두었던 변수에 값이 할당됩니다.

 


참조

https://velog.io/@imacoolgirlyo/JS-%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8%EC%9D%98-Hoisting-The-Execution-Context-%ED%98%B8%EC%9D%B4%EC%8A%A4%ED%8C%85-%EC%8B%A4%ED%96%89-%EC%BB%A8%ED%85%8D%EC%8A%A4%ED%8A%B8-6bjsmmlmgy

https://meetup.toast.com/posts/129