Javascript

코어 자바스크립트 - 실행 컨텍스트

복습의 목적으로 정재남님의 저서 '코어 자바스크립트'를 읽고 정리한 글입니다.

더 자세하고 정확한 내용은 책을 참고하시길 바랍니다.

 

이 챕터를 읽고 난 후 다음의 질문에 답할 수 있어야 한다.

  • 자바스크립트 환경에서 실행 컨텍스트란 무엇인가?
  • 활성화된 실행 컨텍스트에 어떤 정보가 수집되는가?
  • VriableEnvironment와 LexicalEnviroment는 무엇이고 어떤 차이가 있는가?
  • environmentRecord는 무엇이고 호이스팅과 어떤 관련이 있는가?
  • 함수선언문과 함수표현식의 차이는 무엇인가?
  • 스코프와 스코프 체인이란 무엇인가?
  • 변수 은닉화란 무엇인가?

 

실행 컨텍스트란

실행 컨텍스트란 실행할 코드에 제공되는 환경 정보를 모아놓은 객체이다. 동일한 환경에 있는 코드를 실행할 때 필요한 환경 정보들을 모아 컨텍스트를 구성한다. 이를 모두 콜 스택에 쌓아 올렸다가, 순서에 따라 코드를 실행시키게 된다. 어떤 실행 컨텍스트가 콜 스택의 맨 위에 쌓이는 순간이 곧 실행될 코드에 관여하게 되는 순간이다.

 

컨텍스트 수집 정보

  • VriableEnvironment(V.E)
    • environmentRecord(snapshot)
    • outerEnvironmentReference(snapshot)
  • LexicalEnviroment(L.E)
    • environmentRecord(E.R)
    • outerEnvironmentReference(O.R)
  • ThisBinding (식별자가 바라봐야 할 대상 객체)

 

LexicalEnviroment and VriableEnvironment

실행 컨텍스트가 생성될 때 VriableEnvironment(이하 V.E)에 정보를 먼저 담고 나서, 이를 그대로 복사하여 LexicalEnviroment(이하 L.E)를 구성한다. 초기 상태에서는 V.E 와 L.E가 동일하지만, 이후 코드 진행에 따라 서로가 달라질 수 있다.(라고는 하지만 V.E에 대한 설명이 부족한 편이라 이해하기 어려웠다. ECMA 공식 문서에 의하면 아래의 내용을 확인할 수 있다)

 

출처: https://262.ecma-international.org/5.1/#sec-10.3

The LexicalEnvironment and VariableEnvironment components of an execution context are always Lexical  Environments. When an execution context is created its LexicalEnvironment and VariableEnvironment components initially have the same value. The value of the VariableEnvironment component never changes while the value of the LexicalEnvironment component may change during execution of code within an execution context.

공식문서에서도 실행 컨텍스트가 생성될 때 서로 같은 값을 갖는다는 내용과 L.E가 코드가 실행되는 동안 바뀌는 것과 달리 V.E는 초기 값을 유지한다는 내용을 확인할 수 있다. 책에서도 V.E를 아래와 같이 정의하고 있다.

 

현재 컨텍스트 내의 식별자들에 대한 정보 + 외부 환경 정보. 선언 시점의 L.E의 스냅샷으로 변경사항은 반영되지 않음

정리하자면, 컨텍스트가 생성되면 V.E와 L.E가 생성된다.

V.E에 먼저 환경 정보가 저장되고 이는 L.E의 스냅샷으로서 컨텍스트 생성 초기에는 L.E와 같은 값을 가지며,

이후 L.E가 변할 수 있는 것과 달리 V.E는 초기 값을 유지한다.

실제로 한 포스팅에서는 V.E를 아래와 같이 서술하기도 한다.

 

The second part of the lexical environment, the environment record, is an identifier (think, object) representing the variable environment. Again, do not let this new terminology confuse you. the variable environment is truly just a fancy representation of the lexical environment’s local memory. In the environment record, the lexical environment stores variables as well as other information such as the infamous this.

V.E는 L.E의 로컬 메모리를 fancy하게 표현한 것뿐이다.

 

관련 레퍼런스

 

environmentRecord and 호이스팅

L.E를 뜯어보면 outerEnvironmentReference과 environmentRecord로 구성되어 있다.

 

outerEnvironmentReference는 상위 컨텍스트, 즉 부모 컨텍스트의 L.E를 참조한다. 현재 컨텍스트가 실행되는 시점의 L.E를 참조하는 셈이다. 전역 컨텍스트의 경우 상위 컨텍스트가 없기 때문에, 전역 컨텍스트의 outerEnvironmentReference는 null이다.

 

environmentRecord에는 현재 컨텍스트와 관련된 코드의 식별자 정보들이 저장된다. 컨텍스트 내부를 처음부터 끝까지 순서대로 훑어나가면서 순서대로 변수 선언부, 함수 선언문 등을 수집한다. 여기서 호이스팅이라는 개념이 등장한다. environmentRecord로 변수 선언부나 함수 선언문 등이 수집되는 일련의 과정을 통해, 코드가 실행되기 전임에도 불구하고 자바스크립트 엔진은 해당 환경에 속한 코드의 변수명들을 모두 알게 된다. 이러한 작업이 마치 모든 변수 선언부와 함수 선언문이 코드의 최상단으로 끌어올려지는 것처럼 보이기 때문에 호이스팅이라고 부른다. 만약 변수의 선언과 할당이 같은 줄에서 이뤄진다면, 할당부는 그대로 두고 선언부만 올려진다. 함수선언문의 경우엔 전체가 호이스팅된다.

 

함수선언문과 함수표현식의 차이

함수선언문은 그 전체가 호이스팅되는 반면, 함수표현식은 변수에 할당되는 방식이기 때문에 변수의 선언문만 올라가게 되고 할당부, 즉 함수 자체는 그 자리에 남겨지게 된다. 만약 1000줄 위에 선언된 함수의 존재를 모르고 동명의 함수선언문이 아래에서 정의되어 사용되는 상황을 가정해 본다면, 해당 함수를 사용하는 모든 코드에 영향을 끼치게 된다. 에러를 출력하지도 않기 때문에 매우 답답하고 위험한 상황에 노출될 수 있다. 함수표현식을 쓴다면 선언부만 올라가기 때문에 이러한 상황을 미연에 방지할 수 있다. 그러나 더 안전한 것은 내부 컨텍스트를 만들어 함수를 지역 변수로 만드는 것이다.

 

스코프와 스코프 체인

스코프란 식별자의 유효 범위이다. 스코프 내부에서 선언된 변수는 해당 스코프 내에서만 접근 가능하다. 스코프 체인이란, 내부에서 외부로 차례대로 식별자의 유효 범위를 검색해나가는 것을 말한다. outerEnvironmentReference에서 외부 컨텍스트를 참조할 수 있다. 만약 어떤 변수를 찾지 못한다는 것은 스코프 체인을 따라 역 컨텍스트까지 찾아봤지만 존재하지 않음을 의미한다. 전역 컨텍스트에서 내부로 들어갈수록 그 규모는 작아지는 반면, 접근 가능한 변수의 수는 늘어난다.

 

변수 은닉화

전역 컨텍스트와 내부 컨텍스트에 각각 A라는 변수가 존재한다면, 내부 컨텍스트에서는 가장 가까운 내부에서 선언된 A변수만을 참조하기 때문에 전역 공간에서 선언된 동명의 A변수에 접근할 수 없다. 외부에서도 당연히 접근할 수 없다. 이를 변수 은닉화라고 한다.