본문 바로가기
JS

모던 자바스크립트 Deep Dive - 실행 컨텍스트

by 학식러 2024. 1. 17.

 

23장 실행 컨텍스트

 

소스코드의 타입

  • 4가지 타입의 소스코드는 실행 컨텍스트를 생성하고 타입에 따라 실행 컨텍스트 생성 과정, 관리 내용이 다름.

1) 전역 코드

  • 전역 스코프 생성
  • 전역 실행 컨텍스트 생성

 

2) 함수 코드

  • 지역 스코프 생성
  • 함수 실행 컨텍스트 생성

 

3) eval 코드

 

4) 모듈 코드

  • 독립적인 모듈 스코프 생성
  • 모듈 실행 컨텍스트 생성

 

소스코드의 평가와 실행

  • JS엔진은 소스코드를 소스코드 평가 와 소스코드 실행 과정으로 나누어 처리함
  • 평가 과정 : 실행 컨텍스트 생성, 선언문(변수, 함수)만 먼저 실행하여 생성된 변수나 함수 식별자를 키로 실행 컨텍스트가 관리하는 스코프에 등록함.
  • 평가 과정 후 : 선언문 제외 소스코드 순차적으로 실행. === 런타임 실행소스코드 실행에 필요한 정보(변수, 함수 참조)를 실행 컨텍스트가 관리하는 스코프에서 검색하여 취득
  • 소스코드의 실행 결과는 실행 컨텍스트가 관리하는 스코프에 등록됨.

 

실행 컨텍스트의 역할

23-02

// 전역 변수 선언
const x = 1;
const y = 2;

// 함수 정의
function foo(a) {
  // 지역 변수 선언
  const x = 10;
  const y = 20;

  // 메서드 호출
  console.log(a + x + y); // 130
}

// 함수 호출
foo(100);

// 메서드 호출
console.log(x + y); // 3

 

1) 전역 코드 평가

  • 선언문 먼저 실행 : 전역 변수, 전역 함수가 실행 컨텍스트의 관리를 받는 전역 스코프에 등록됨.

 

2) 전역 코드 실행

  • 런타임 시작, 전역 코드 순차적 실행, 전역변수에 값 할당, 함수 호출됨

 

3) 함수 코드 평가

  • 함수 호출에 의해 함수 내부로 진입, 함수 내부 코드 실행 전 함수 코드 평가.
  • 매개변수, 지역변수 선언문이 먼저 실행되고 지역 스코프에 등록됨
  • 지역변수처럼 쓰는 arguments 객체 생성되어 지역 스코프에 등록됨, this 바인딩 결정됨.

 

4) 함수 코드 실행

  • 런타임 시작, 함수 코드 순차적 실행
  • 매개변수, 지역변수에 값 할당됨
  • console.log 메서드 호출
    • console을 스코프 체인을 통해 검색.
    • 함수 코드의 지역 스코프는 상위 스코프인 전역 스코프와 연결되어야함.
    • 하지만 console은 스코프 체인에 등록되어있지 않고 전역 객체에 프로퍼티로 존재함.⇒ 전역 객체의 프로퍼티가 전역 스코프를 통해 검색 가능해야함을 의미.
    • log 프로퍼티를 console 객체의 프로토타입 체인을 통해 검색
    • a+x+y 평가됨
    • ….

 

  • 코드가 실행되려면 스코프를 구분하여 식별자, 바인딩된 값이 관리되어야함.
  • 스코프 체인 형성하여 식별자 검색할 수 있어야함.

 

  • 실행 컨텍스트 : 이 모든 것을 관리, 소스코드 실행 필요 환경 제공, 코드의 실행 결과를 실제로 관리.
  • 식별자(변수, 함수, 클래스 등의 이름)를 등록, 관리하는 스코프, 코드 실행 순서 관리를 구현한 내부 메커니즘.
  • 식별자와 스코프는 렉시컬 환경으로 관리, 코드 실행 순서는 실행 컨텍스트 스택으로 관리.

 

실행 컨텍스트 스택

23-03

const x = 1;

function foo () {
  const y = 2;

  function bar () {
    const z = 3;
    console.log(x + y + z);
  }
  bar();
}

foo(); // 6

 

 

 

1) 전역 코드의 평가와 실행

  • 전역코드 평가 : x, foo 전역 실행 컨텍스트에 등록됨.
  • 전역코드 실행 : x에 값 할당, foo 호출.

 

2) foo 함수 코드의 평가와 실행

  • foo함수 내부 코드 평가 : foo 함수 실행 컨텍스트 생성, foo함수 지역변수 y, 중첩함수 bar 컨텍스트에 등록됨.
  • foo 함수 코드 실행 : 지역 변수 y에 값 할당, 중첩 함수 bar 호출.

 

3) bar 함수 코드의 평가와 실행

  • bar함수 내부 코드 평가 : bar 함수 실행 컨텍스트 생성, bar 함수 지역변수 z 실행 컨텍스트에 등록됨.
  • bar 함수 코드 실행 : 지역 변수 z에 값 할당, console.log 메서드 호출, bar 종료.

 

4) foo 함수 코드로 복귀

  • bar 함수 실행 컨텍스트를 스택에서 제거. foo 종료

 

5) 전역 코드로 복귀

  • foo 함수 실행 컨텍스트를 스택에서 제거. 모두 종료.

 

 

  • 실행 컨텍스트 스택은 코드의 실행 순서를 관리.

 

렉시컬 환경

  • 식별자, 상위 스코프에 대한 참조를 기록.
  • 스코프와 식별자를 관리

 

구성 컴포넌트

  • 환경 레코드 : 스코프에 포함된 식별자를 등록, 값을 관리하는 저장소
  • 외부 렉시컬 환경에 대한 참조 : 상위 스코프를 가리킴.

 

실행 컨텍스트의 생성과 식별자 검색 과정

23-04

var x = 1;
const y = 2;

function foo (a) {
  var x = 3;
  const y = 4;

  function bar (b) {
    const z = 5;
    console.log(a + b + x + y + z);
}
  bar(10);
}

foo(20); // 42

1. 전역 객체 생성

2. 전역 코드 평가

1) 전역 실행 컨텍스트 생성

2) 전역 렉시컬 환경 생성

2-1) 전역 환경 레코드 생성

a) 객체 환경 레코드 생성 : var, 함수선언문

  • 1단계 전역 객체 생성에서 만들어진 BindingObject 객체와 연결됨.
  • x변수는 var로 선언함 ⇒ 선언 단계, 초기화 단계 동시에 진행.
  • 호이스팅이 발생하는 이유: 전역 코드 평가 시점에 전역 객체에 변수 식별자를 키로 등록 후, 암묵적으로 undefined 바인딩. 따라서 var 변수는 변수 선언문 이전에도 참조 가능.

b) 선언적 환경 레코드 생성 : let,const

  • const 변수는 선언단계, 초기화 단계가 분리되어 진행.
  • 초기화단계(변수 선언문에 도달하기)전 까지 일시적 사각지대(TDZ)에 빠지게 됨.
  • let, const도 호이스팅 발생함.
  • 하지만 런타임에 컨트롤이 변수 선언문에 도달 전까지 TDZ에 빠지기 때문에 참조 불가.

23-07

let foo = 1; // 전역 변수

{
  // let, const 키워드로 선언한 변수가 호이스팅되지 않는다면 전역 변수를 참조해야 한다.
  // 하지만 let 키워드로 선언한 변수도 여전히 호이스팅이 발생하기 때문에 참조 에러(ReferenceError)가 발생한다.
  console.log(foo); // ReferenceError: Cannot access 'foo' before initialization
  let foo = 2; // 지역 변수
}

 

2-2) this 바인딩

2-3) 외부 렉시컬 환경에 대한 참조 결정

  • 현재 평가중인 소스코드 포함하는 외부 소스코드의 렉시컬환경, 즉 상위 스코프를 가리킴.

 

3. 전역 코드 실행

4. foo 함수 코드 평가

1) 함수 실행 컨텍스트 생성

2) 함수 렉시컬 환경 생성

2-1) 함수 환경 레코드 생성

2-2) this 바인딩

2-3) 외부 렉시컬 환경에 대한 참조 결정

5. foo 함수 코드 실행

6. bar 함수 코드 평가

7. bar 함수 코드 실행

8. bar 함수 코드 실행 종료

9. foo 함수 코드 실행 종료

10. 전역 코드 실행 종료

 

실행 컨텍스트와 블록 레벨 스코프

23-11

let x = 1;

if (true) {
  let x = 10;
  console.log(x); // 10
}

console.log(x); // 1
  • if블록이 실행되면 블록 스코프를 생성해야함.
  • 이를 위해, 선언적 환경 레코드를 갖는 렉시컬 환경을 새롭게 생성해야함.

 

댓글