실행 컨텍스트

김동현·2023년 1월 2일
0

자바스크립트

목록 보기
4/22

실행 컨텍스트란 무엇인가?

자바스크립트 코드를 실행할 때 필요한 정보들을 저장하고 제공하는 환경이다.
즉, 스코프의 정보를 담은 환경을 의미한다.

console.log('global context');

function foo(){
  console.log('foo context');
}

function bar(){
  foo();
  console.log('bar context');
}

bar();

// 출력결과
// global context
// foo context
// bar context

실행 컨텍스트의 구성 요소

실행 컨텍스트는 아래 두 가지 컴포넌트로 구성된다.

  • Lexical Environment ( 이하 LE )

  • Variable Environment ( 이하 VE )

그리고 이 두 가지 컴포넌트는 Environment Records ( 이하 ER )라 불리는 형태로 구성되어 있다.

ES5와 ES2015의 실행 컨텍스트와 변경된 점이 있다.

  • this 바인딩에 대한 정보는 ES5에서는 실행 컨텍스트에 별도로 저장되었지만, ES2015 이후부터는 ER에서 this에 대한 정보를 저장한다.
  • 이전 ES2015 명세에서는 LE 하위의 구성요소로 ER과 상위 LE에 대한 참조 정보를 저장하였다.
    하지만 현재 명세에서는 ER에서 식별자, this 바인딩, 상위 ER에 대한 참조까지 저장한다.
  • LE와 VE가 ER 자체를 바인딩하는 형태로 변경되었다. ECMAScript 에서는 '실행 컨텍스트의 LE와 VE는 항상 ER이다'라고 표현하고 있다.
function foo(){
  const a = 1;
  var b = 2;
  console.log(a, b);
}

위 코드의 실행 컨텍스트 구성요소는 아래와 같다.

  • Foo LE < Foo ER >

    a1
    ThisBindingundefined
    OuterEnvGlobal ER
  • Foo VE < Foo ER >

    b2
    ThisBindingundefined
    OuterEnvGlobal ER

Environment Records와 스코프 체인

ER은 렉시컬 스코프를 기반으로 특정 변수와 함수에 대한 식별자의 연결 정보를 저장한다.
쉽게말해 코드가 실행되면 변수나 함수에 대한 식별자를 선언하고, 코드가 한 줄 한 줄 실행될 때마다 선언된 식별자에 값을 할당할 수 있도록 바인딩하는 것이다.

함수 선언, 블록문 또는 try-catch와 같은 구문들이 평가될 때 식별자 바인딩을 위해 새로운 ER이 생성된다.

모든 ER에는 OuterEnv 필드가 있으며, 이 필드는 상위 렉시컬 스코프에 대한 ER을 참조한다.
최상위 실행 컨텍스트인 전역 컨텍스트에서는 참조할 상위 스코프가 없기 때문에 OuterEnv 필드는 null이 된다.

function foo(){
  va a = 1;
  function bar(){
    console.log(a); // 1
  }
  bar();
}
foo();
  • Bar VE < Bar ER >

    ThisBindingundefined
    OuterEnvFoo ER
  • Foo VE < Foo ER >

    a1
    ThisBindingundefined
    OuterEnvGlobal ER
  • Global VE < Global ER >

    ThisBindingundefined
    OuterEnvnull

Bar ER은 OuterEnv 필드를 통해 상위 렉시컬 스코프에 대한 Foo ER을 참조할 수 있다.
만약 실행 컨텍스트에서 코드가 실행될 때 Bar ER에 a라는 식별자가 없다면 OuterEnv 필드를 통해 Foo ER에서 식별자 a를 찾을 수 있다.
앞에서 보았던 스코프 체인의 원리가 바로 이것이다.

사실 스코프 체인이라는 말은 ES3 이후로 명세에서 사용되지 않는 용어이다.
Lexical Environment 개념이 도입된 이후 ECMAScript 명세에서는 lexical nesting structure라는 용어를 사용한다.


다양한 Environment Records

ER은 추상 클래스로서 이를 세부적으로 구현하는 3가지의 하위 ER이 있다.

declarative ER
변수, 상수, 클래스 모듈 또는 함수 선언 등 렉시컬 스코프 내에서 선언된 식별자들을 바인딩한다.

그리고 declarative ER의 하위에는 2가지의 하위 ER이 있다.

  • function ER
    함수 내의 최상위 위치에 선언한 식별자들을 바인딩한다.
    함수에서 사용되는 this값과 new.target ( 함수가 new 연산자를 사용하여 호출되었는지 알 수 있는 프로퍼티이다 ) 에 대한 정보를 가진다.
    그리고 화살표 함수가 아닌 경우에만 this를 바인딩하며, super로 상위 클래스에 대한 정보를 바인딩한다.

  • module ER
    모듈의 외부 스코프를 나타내는 정보를 추가적으로 바인딩한다.
    다른 ER에 존재하는 식별자에 간접적으로 접근할 수 있는 가져오기 ( import ) 바인딩을 제공한다.

object ER
binding object라는 객체의 프로퍼티들을 식별자로 바인딩한다.
binding object 객체의 프로퍼티들은 side effect에 의해 동적으로 변경될 수 있다.

global ER
최상위 전역 스코프에서 선언된 식별자와 전역 객체에 대한 바인딩을 한다.
global ER은 특이하게도 declarative ER과 object ER을 합성한 형태이다.
object ER은 내장 전역 객체와 var 변수, 함수 선언문으로 선언된 식별자들에 대한 바인딩을 binding object로 가지고 있으며, 이 binding object가 우리가 window로 접근하는 전역객체이다.
그 외의 나머지 식별자들에 대한 바인딩은 declarative ER에서 저장하며, 이를 우리가 전역 변수라고 한다.

profile
프론트에_가까운_풀스택_개발자

0개의 댓글