자바스크립트를 이해해보자 (1)

손성호·2025년 2월 23일

자바스크립트의 중요 특성들 (호이스팅, 프로토타입 체인, this, 클로저)에 대해 알기 전 실행 컨텍스트를 이해하면 좋습니다.
실행 컨텍스트에 대해 먼저 알아보고, 다른 주요 특성들 또한 정리해보려고 합니다.

실행컨텍스트의 정의

실행컨텍스트는 코드가 실행되는 환경입니다.
여기서 코드는 크게 3가지로 나눌 수 있습니다.
1. 전역코드
2. 함수코드
3. eval코드
eval함수의 경우 안티패턴이므로 여기서는 2가지만 알아보려고 합니다.

실행컨텍스트의 실행

실행컨텍스트가 코드를 실행하는 순서는, 스택 자료구조와 동일하다.
실행할 코드들을 스택처럼 콜스택에 쌓고 위에서 부터 Pop하며 동작하는 식으로 작동한다.
위에서 두가지 코드 종류 중 전역코드가 제일 먼저 실행컨텍스트에 쌓이게 된다.
이를 전역 컨텍스트라고한다.
전역 컨텍스트는 하나만 생성된다.
이후 코드를 실행하면서, 함수를 호출하게되면 함수 컨텍스트가 생성되어 실행컨텍스트에 쌓이게 된다.

실행 컨텍스트 실행순서
[그림1] 실행컨텍스트의 실행순서

실행 컨텍스트는 스택(LIFO)처럼 작동하므로 위에서부터 Pop하면서 작동한다.

함수실행이 끝나면 해당 컨텍스트는 사라진다.

함수 컨텍스트가 다 종료된 후에 글로벌 컨텍스트가 호출된다.

실행컨텍스트의 구성요소

실행 컨텍스트는 객체형태를 띄고 있으며 3가지 속성을 가지고 있다. (ES3)

js에서 무슨 타입인지 모르겠으면 객체라고 찍자

  • 변수객체
  • 스코프체인
  • this

이렇게 3가지 속성을 가진다.

'executionContext': {
	variableObject: {},
	scopeChain: [],
	this,
};

수정

변수객체라는 개념은 ES3에 있던 개념입니다. ES5부터 환경레코드라는 개념으로 실행컨텍스트의 구성요소가 바뀌었습니다. 나름 열심히 작성한 것 같아서 지우진않고 남기려고합니다.

ES5이후부턴 실행컨텍스트가 환경레코드와 this로 구성되어있습니다.

  • 렉시컬 환경
  • 변수 환경
  • this

3가지로 크게 나눌 수 있습니다.

function conceptualExecutionContext() {
  return {
    // 렉시컬 환경
    LexicalEnvironment: {
      // 환경 레코드 (변수, 함수 등 식별자 저장)
      environmentRecord: {
        // let, const 선언, 함수 표현식 등
        identifiers: {
          x: '<uninitialized>', // TDZ 상태
          y: 20,
          fnExpr: function() {}
        }
      },
      // 외부 렉시컬 환경에 대한 참조 (스코프 체인)
      outerEnvironmentReference: /* 외부 렉시컬 환경 참조 */
    },
    
    // 변수 환경 (var, 함수 선언문 저장)
    VariableEnvironment: {
      environmentRecord: {
        identifiers: {
          a: undefined, // var 호이스팅 (undefined로 초기화)
          fnDecl: function() {} // 함수 선언 (전체가 호이스팅)
        }
      },
      outerEnvironmentReference: /* 외부 렉시컬 환경 참조 */
    },
    
    // this 바인딩
    ThisBinding: /* 함수 호출 방식에 따라 결정되는 this 값 */
  };
}

Variable Environment

함수가 처음 호출 시엔 렉시컬 환경과 변수 환경이 동일합니다.
현재 컨텍스트 내의 변수들에 대한 정보를 가지고 있습니다.
다만 함수 호출 시 생성된 환경의 스냅샷을 변경하지 않고 계속 유지합니다. (함수 스코프 유지를 위해)

Lexical Environment

LexicalEnvironment는 environmentRecord와 outerEnvironmentReference를 갖고 있습니다.

  • environment Record를 통해 호이스팅이 발생합니다.
    환경 코드엔 현재 컨텍스트와 관련된 식별자 정보들이 저장됩니다. (호이스팅 발생)
    호이스팅 시, 실제로 변수를 끌어 올리는건 아니고 편의상 끌어올리는걸로 간주한다.

  • outerEnvironmentReference를 통해 스코프와 스코프 체인이 형성됩니다.
    외부환경참조는 현재 호출된 함수가 선언될 당시의 Lexical Environment를 참조합니다.

이틀정도 V8엔진 구현 코드를 보았는데.. 참 어렵다 ㅠ 리액트보다 어렵게 되어있는 것 같다.
context가 내가 생각하는 context가 아닌 것 같았다. 실행컨텍스트보단 하나의 단위 인 것 같다.
추측으론 외부환경참조가 큐처럼 되어있어서, 스코프체인구조가 가능한게 아닌가 싶다.

---- 이하는 이전에 작성한 글입니다 ----

변수객체 (V.O : Variable Object)

실행컨텍스트가 생성되면, 실행에 필요한 정보를 담을 객체를 생성한다. 이를 변수객체 라고한다.
변수객체는 세가지 정보를 담는다.

  • 변수
  • Parameter & Argument (엄연히 다르다 둘은)
  • 함수 선언

위에서 컨텍스트는 두가지 종류가 있다고 했다.

전역과 함수. 전역 컨텍스트와 함수 컨텍스트는 다른 변수객체를 가진다.

전역 컨텍스트의 변수 객체

전역 컨텍스트의 변수 객체는 모든 전역 변수 및 전역 함수등을 포함하는 전역 객체(Global Object)를 생성한다. 전역객체는 전역에 선언된 모든 전역 변수와 전역함수를 프로퍼티로 갖게 된다.

함수 컨텍스트의 변수 객체

함수 컨텍스트는 활성 객체(Activation Object)를 생성한다. 또한 인수들의 정보를 배열로 담고 있는 유사배열객체 Argument Object를 추가로 생성한다.

스코프 체인 (Scope Chain)

스코프 체인은 현재 컨텍스트의 유효범위를 나타내는 스코프 정보를 담고 있으며, 변수 객체들이 차례대로 연결된 리스트 형태를 가진다. 리스트를 통해 현재 컨텍스트의 변수와 상위 실행 컨텍스트의 변수에도 접근할 수 있다.

현재 실행 컨텍스트의 변수 객체를 먼저 가리키고, 순차적으로 상위 컨텍스트의 변수 객체를 가리킨다.

이런 스코프 체인구조덕에 클로저가 가능해진 것이다! (클로저 의문해결)

var x = 1

function foo() {
  var arg = arguments
  var y = 2

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

foo()

이런 코드가 있다고 가정하자.

foo함수는 arguments, bar(), y를 가르키고 있는 활성객체를 변수객체로 갖게 된다. 그리고 스코프 체인에 이 활성객체가 들어가 있다.

ActivationObject = {
    arguments: { /* arguments 객체 */ },
    bar: <Function>,  // 함수 선언
    y: "some value"   // 변수
}

'fooExecutionContext': {
	variableObject: ActivationObject,
	scopeChain: [ActivationObject, GlobalObject],
	this: <thisBinding>
};
  
const GlobalObject = {
    foo: <Function>,
    x: "global value",
    // 빌트인 객체들...
    window: this,
    Math: <Object>,
    String: <Function>
    // ...
};

  
'GlobalExecutionContext': {
	variableObject: GlobalObject,
	scopeChain: [GlobalObject],
	this: GlobalObject,
};
  

이런식으로 실행컨텍스트가 이루어져있다고 생각하면 된다.

자바스크립트 엔진은 스코프 체인을 활용해서 렉시컬 스코프를 파악한다. 함수 실행중에 변수를 만나면 해당 변수를 현재 스코프의 변수객체(엄밀하겐 활성객체이다 함수컨텍스트니까)에서 검색하보고 검색에 실패하면 스코프체인을 따라서 순서대로 한 단계씩 위로 검색을 이어간다.

만약 검색에 실패했다면? 정의되지 않은 변수에 접근하는 것으로 인식하여 Reference에러가 발생하게 된다.

What is this?

실행컨텍스트가 가지는 3가지 속성 중 this는 자바스크립트에서 생각보다 큰 범위이기에 따로 나누어 설명하려고 합니다.

링크를 참조하세요.

정리

실행 컨텍스트는 2가지 종류(전역컨텍스트, 함수컨텍스트)로 나뉜다.

실행컨텍스트는 3가지 속성(어휘적 환경,변수 환경,this)을 가진다.

참고자료

Javascript Execution Context
Do you know vanilla?
실행 컨텍스트(Execution Context)와 호이스팅(Hoisting)
Inpa Dev
개발자 황준일님

잘못된, 오타난 부분은 지적해주시면 감사합니다.
3/11 잘못된 개념 수정 (객체 -> 환경레코드)

profile
사용자를 위한 웹화면을 개발하고 있습니다.

0개의 댓글