실행컨텍스트와 실행스택에 대해

실행컨텍스트란? js코드가 평가되고 실행되는 환경이다.

실행 컨텍스트에는 전역실행컨텍스트와 함수실행컨텍스트가 있다.

전역컨텍스트

프로그램당 하나밖에 없다. window 전역객체를 만들고 this를 전역객체와 동일하게 설정한다. 생성 시점은 자바스크립트 엔진이 스크립트를 만날 때이다. var 등 선언문을 만나면 저장해둔다.

함수 실행 컨텍스트

함수가 실행될 때마다 그 함수의 새 컨텍스트가 생긴다. 선언이 아니다.

실행스택

코드 실행하는 동안에 생성된 모든 실행컨텍스트를 저장한다.

자바스크립트가 실행될 때 전역실행컨텍스트를 생성하고 현재 실행스택에 넣는다. 함수호출을 찾을 때마다 실행스택에 쌓는다. js 엔진은 스택 제일 상위 함수를 실행하고 그 컨텍스트는 스택에서 빠져나온다.

js 엔진에 의해 실행컨텍스트는 어떻게 생성되는가?

실행컨텍스트 생성에는 두 단계가 있다. 1. 생성 단계, 2. 실행 단계
또한 실행컨텍스트에는 LexicalEnvironment와 VariableEnvironment가 있다.

생성 단계

1. LexicalEnvironment 생성

변수 매핑을 한다.

let a = 1;

function b() {
	console.log('c');
}
//위 코드의 LexicalEnvironment는? 아래와 같다.

LexicalEnvironment = {
	a: 1,
	b: <b 함수 참조>
}

LexicalEnvironment는 3가지 구성요소가 있다.

  1. 환경 기록 - 변수, 함수 선언을 저장한다.
  2. 외부 환경에 대한 참조 - 외부 LexicalEnvironment에 접근.현재 환경에 변수가 없을 경우 외부에서 찾는다.
  3. this 바인딩 - 글로벌실행컨텍스트에서는 글로벌 오브젝트에 바인딩 된다.(window일 경우 Window), 함수 실행컨텍스트의 경우 함수가 어떻게 호출되느냐에 따라 다르다.

    //this binding 설명
    const person = {
      name: 'yonyas',
      getName: function() {
        console.log(this.name);
      },
    };
    
    person.getName(); // 'this'는 person
    
    const getName = person.getName;
    getName(); // 'this'는 window, strict모드라면 undefined

LexicalEnvironment의 구조

전역실행컨텍스트 = {
  LexicalEnvironment: {
    환경기록: {a: 10, b: 20 ... },
    외부참고: <null>,
    this: Window
  }
}

함수실행컨텍스트 = {
  LexicalEnvironment: {
    환경기록: {a: 10 ... },
    외부참고: 전역 or 외부함수,
    this: (함수가 선언되는 방식에 따라 다르다.)
  }
}

2. VariableEnvironment 생성

  이 또한 LexicalEnvironment인데 차이점은 환경기록에 var을 들고 있다. LexicalEnvironment는 const, let을 들고 있다.

실행 단계

이 단계에서 할당이 완료되고 최종적으로 실행된다.
생성단계에서 var: a 의 환경기록이 {a: undefined} 이고 실행단계에서 {a: 10}으로 바뀐다.
이 때 let: a 는 생성단계에서 {a: <uninitialized>이기 때문에 var와 다르게 호이스팅이 일어나지 않는다.

출처

https://blog.bitsrc.io/understanding-execution-context-and-execution-stack-in-javascript-1c9ea8642dd0


Written by@Jiyon Lee
뜨거운 코드를 가르며

GitHub