JS | Execution Context 실행 컨텍스트

Autumn·2021년 6월 6일
3

JavaScript

목록 보기
18/18
post-thumbnail
post-custom-banner

자료구조, 알고리즘 공부를 슬슬 해야겠다는 생각이 들어서 트리 구조에 대해 공부하다가 JS로 구현된 코드를 만났다.

class Node {
  constructor(data) {
    this.data = data;
    this.children = [];
  }

  add(data) {
    this.children.push(new Node(data)); 👈 🔥
  }

  remove(data) {
    this.children = this.filter((child) => child.data !== data);
  }
}

class Tree {
  constructor() {
    this.root = null;
  }
}

const t = new Tree();
t.root = new Node('a');
t.root.add('b');
t.root.add('c');
t.root.children[0].add('d');

console.log(t);

그런데 문득 👈 🔥 이 부분이 궁금해졌다.

Node 라는 Class 의 정의가 다 끝나지 않았는데 어떻게 new Node 라고 접근이 가능한 거지..?

클래스라서 가능한 걸까? 궁금해서 아주 간단한 코드를 작성해보았다.

const a = () => {
  console.log('a 함수');
  console.log(a);
};

a();

// 👇 결과
// a 함수
// [Function: a]

여기서도 a 함수의 정의가 끝나지 않았는데(?) console.log(a) 에서 에러 없이 [Function: a] 라고 출력이 된다. 생각해보면 재귀 함수를 쓸 때도 별 생각 없이 이런 식으로 코드를 작성했었는데, 어떤 원리로 동작하는 것인지 실행 컨텍스트 라는 키워드를 통해 알아보자.


예제 코드

let x = 10;

function timesTen(a) {
  return a * 10;
}

let y = timesTen(x);

console.log(y); // 100

위 코드에서는

  1. x 라는 변수에 10을 할당한다.
  2. 인자를 받아 10을 곱하는 timesTen 함수를 선언한다.
  3. x를 파라미터로 전달하여 timesTen 함수를 호출하고, 그 리턴값을 y 라는 변수에 저장한다.
  4. y 를 콘솔에 찍어본다.

실행 컨텍스트

자바스크립트 엔진이 스크립트를 실행할 때, 실행 컨텍스트들을 생성한다. 각각의 실행 컨텍스트는 2개의 phase를 갖는다. the creation phase and the execution phase


The creation phase

맨 처음 스크립트가 실행될 때, 자바스크립트 엔진은 Global Execution Context 를 생성한다. Global Execution Contextcreation phase 에서는 다음과 같은 일을 한다.

  • global object를 생성한다. 웹 브라우저에서는 window, Node.js에서는 global 이다.
  • this object를 생성한다. 이 this는 위에서 언급한 global object에 binding된다. (this === window 혹은 this === global 이라는 뜻)
  • 변수와 함수의 참조를 저장할 memory heap을 setup한다.
  • global context 안에 있는, memory heap에 있는 함수 선언과 변수들을 초기값 undefined 로 해서 저장한다.

예제 코드의 creation phase 동안에는

  • 자바스크립트 엔진이 변수 x, y, 함수 선언 timesTen을 Global Execution Context에 저장한다. 그리고 변수 x, yundefined로 초기화한다.

creation phase 다음에는, global execution context는 execution phase로 옮겨간다.


The execution phase

execution phase 동안에는, 자바스크립트 엔진이 코드를 한 줄 한 줄 실행한다. 변수에 값(values)을 할당하고, function calls를 실행한다.

매 함수 호출마다, 자바스크립트 엔진은 새로운 Function Execution Context를 생성한다. funtion execution context는 global execution context와 비슷한데, global object를 생성하는 대신 arguments object를 생성한다. arguments object는 함수에게 전달된 모든 파라미터의 reference를 가지고 있다.

예제 코드에서는, function execution context가 함수에게 전달된 파라미터의 references를 가지고 있는 arguments object를 생성하고, this에 global object를 셋팅하고, 파라미터인 aundefined로 초기화한다.

function execution context의 execution phase 동안에는, 파라미터 a10을 할당하고 global execution context에게 결과값 100을 리턴한다.

이러한 작업을 위해 자바스크립트 엔진은 call stack 이라는 자료구조를 사용한다.


궁금증 해결하기

그럼 다시 처음에 작성했던 코드를 살펴보자.

const a = () => {
  console.log('a 함수');
  console.log(a);
};

a();

// 👇 결과
// a 함수
// [Function: a]

최초에 Global Execution Context가 생성되면,
1. the creation phase 에서는

  • global object 생성
  • this를 global object에 binding
  • setup the memory heap
  • memory heap에 함수 선언(a)과 변수(없음)를 undefined로 초기화해서 저장. 즉, 변수 aundefined인 상태

2. the execution phase 에서는
👉 코드를 한 줄씩 실행하면서, 변수에 값 할당하는 코드가 있다면 할당하고, 함수 호출을 만나면 Function Execution Context를 실행한다.

  • a함수 () => { ... } 를 할당 🍎🍎🍎
  • 함수 호출 a(); 를 만나면 함수 a의 Function Execution Context 생성

3. 함수 a의 Function Execution Context의 the creation phase

  • arguments object 생성, 여기에는 함수에 전달된 인자들의 references가 저장됨
  • global object에 this binding
  • 해당 함수의 실행 컨텍스트 안에 함수 선언이나 변수 정의가 있다면, undefined로 초기화해서 저장. 우리 예제에서는 저장할 함수 선언이나 변수가 없다.

4. 함수 a의 Function Execution Context의 the execution phase

  • 함수 a 블럭 안에 있는 코드를 한 줄씩 실행
  • console.log 또한 Function Execution Context가 생성되지만 과정 생략..
  • console.log가 호출되니 콜스택에 올라가서 실행되어 a 함수 라고 콘솔에 찍힘
  • 두 번째 console.log 또한 호출되어 실행되는데 a를 콘솔에 찍어야 함
  • 근데 a가 뭐야?? 함수 a의 Function Execution Context 안에 저장된 variables 중에는 a 라는 게 없음
  • scope chain을 타고 올라가자!! Global Execution Context 에서 a를 찾아봄
  • Global Execution Context 의 execution phase에서 🍎🍎🍎 이 때 a에 함수를 할당했었음. 이 정보를 가져온다.
  • 콘솔에 [Function: a] 라고 출력

이 이후에는 함수 a의 Function Execution Context가 콜스택에서 지워지며 Global Execution Context로 돌아가고, Global Execution Context에도 남아있는 코드가 없으므로 Global Execution Context 또한 콜스택에서 지워지며 스크립트가 종료된다.


마무리

차근차근 과정을 생각해보니, 실행 컨텍스트 뿐 아니라 스코프 체인이라는 원리도 적용되어 있다는 것을 알게 되었다. 자바스크립트의 동작에는 정말 모든 개념들이 맞물려있다는 생각이 든다. 다음에는 스코프 체인에 대해서 정리해봐야겠다.

profile
한 발짝씩 나아가는 중 〰 🍁 / 자잘한 기록은 아래 🏠 아이콘에 연결된 노션 페이지에 남기고 있어요 😎
post-custom-banner

4개의 댓글

comment-user-thumbnail
2021년 6월 6일

쉽게 이해가 되도록 잘써주셨네요! 👍👍👍

1개의 답글

예시 코드를 보면서 그냥 넘길 수도 있었던 부분인데 끝까지 파고드는 모습이 멋지네요ㅎㅎ 오톰 글 읽으며 정리할 수 있었어요~~🍉 짱짱!

답글 달기
comment-user-thumbnail
2021년 9월 26일

댓글테스트

답글 달기