실행 컨텍스트란?

aa·2022년 10월 24일
0

개념

목록 보기
4/6

실행 컨텍스트가 뭐죠?

실행할 코드에 제공할 환경 정보들을 모아놓은 객체

자바스크립트를 실행하면 곧 바로 '전역 컨텍스트'가 콜 스택에 쌓인다.
이후, 함수를 실행 할 때마다 해당 함수에 대한 컨텍스트가 차례로 콜 스택에 쌓이게 되고
함수가 종료되면 차례로 스택에서 제거 된다.

아래 코드는 다음과 같은 순서로 스택에 쌓이게 된다.

function first(){
  function second(){
    console.log('second');
  }
  second();
}

first();

1) 콜 스택 비어있음
2) 전역 컨텍스트
3) 전역 컨텍스트 -> first
4) 전역 컨텍스트 -> first -> second
5) 전역 컨텍스트 -> first
6) 전역 컨텍스트
7) 콜 스택 비어있음


자바스크립트가 실행 될 때 컨텍스트가 이런식으로 쌓인다는 점은 알게 되었다.
첫 줄 정의에서 '컨텍스트는 실행할 코드에 제공할 환경 정보들을 모아놓은 객체'라고 했는데
구체적으로 어떤 정보들이 들어가는 걸까?

  1. VariableEnvironment
    현재 컨텍스트 내의 식별자들에 대한 정보 + 외부 환경 정보
    선언 시점의 LexicalEnvironment의 스냅샷으로 변경사항은 저장되지 않음.
    1. environmentRecord
    2. outerEnvironmentReference
  2. LexicalEnvironment
    처음에는 VariableEnvironment와 같지만 변경사항이 실시간으로 반영됨.
    1. environmentRecord
    2. outerEnvironmentReference
  3. ThisBinding
    this 식별자가 바라봐야 할 대상 객체

environmentRecord

현재 컨텍스트와 관련된 코드의 식별자 정보들이 저장된다.
컨텍스트 내부 전체를 쭉 훑으면서 순서대로 수집

  • 매개변수 이름, 함수 선언, var(변수명) 등
  • 값 할당에는 관심 없음 어떤 식별자가 있는지에만 관심

🔍 아직 코드가 실행되기 전이지만 자바스크립트는 해당 코드의 변수명, 함수들을 이미 알고 있는 상태
=> '자바스크립트 엔진은 식별자들을 최상단으로 끌어올리고 실제 코드를 실행한다'고 생각할 수 있음.
=> '호이스팅' 개념 (hoist + ing : 끌어올리다)
먼저 읽어들인 것을 편의상 끌어 올린다고 간주

호이스팅 예시

function a() {
  console.log(b);
  var b = 'bbb';
  console.log(b);
  function b() {}
  console.log(b);
}
a();
  1. 호이스팅에 의해 변수 b를 선언
  2. 함수b 전체를 선언
    변수 b와 연결된 공간에 b함수가 저장된 주소를 저장. 변수 b는 함수를 가리킴
  3. 첫번째 콘솔로그 => 함수가 출력됨.
  4. 데이터 영역에 'bbb'를 저장하고 그 주소를 b 변수에 덮어씌움
  5. 두번째 콘솔로그 => 'bbb'가 출력됨.
  6. 세번째 콘솔로그 => 'bbb'가 출력됨.

실행 컨텍스트의 environmentRecord에 의해 식별자 정보만 먼저 저장되고 '호이스팅'을 발생시킨다.

outerEnvironmentReference

식별자에 대한 유효범위를 '스코프'라고 부른다.
가령 함수 안에서 선언한 변수는 해당 함수 안에서만 사용 가능하고 함수 외부에서는 사용 불가능 하다.
=> 스코프의 개념

ES5까지의 자바스크립트는 오직 함수에서만 이러한 스코프가 생성되었지만,
ES6 부터는 블록{}에 의해서도 스코프가 생성된다.

이러한 스코프의 유효 범위를 안에서 바깥으로 찾아가는 것을 '스코프 체인'이라고 하며 이를 가능하게 하는 것이 outerEnvironmentReference

outerEnvironmentReference는 현재 호출된 함수가 선언될 당시의 LexicalEnvironment를 참조한다.

만약 함수A 내부에 B를 선언했다면 함수B의 outerEnvironmentRefernce는 함수A의 LexcialEnvironment를 참조한다.
이런 특성 때문에 여러 스코프에서 동일한 식별자를 선언한 경우에는 스코프 체인 상 가장먼저 발견된 식별자에 접근 가능하다.


스코프 체인을 통해 environmentRecord 및 outerEnvironmentReference 이해하기

var a = 1;
var outer = function () {
  var inner = function () {
    console.log(a);
    var a = 3;
  };
  inner();
  console.log(a);
};
outer();
console.log(a);
  1. 바로 전역컨텍스트 활성화 environmentRecord에 {a, outer} 저장
    전역은 선언 시점이 있을 수 없으므로 outerEnvironmentReference는 비어있음
  2. 변수 a와 outer에 각각 1과 함수를 할당
  3. outer 함수 실행 전역컨텍스트는 잠시 중단되고 outer 컨텍스트 활성화
  4. outer 컨텍스트의 environmentRecord에 {inner} 저장
    outerEnvironmentReference 에서는 선언 시점의 LexicalEnvironment 정보를 가져옴
    => 전역 컨텍스트의 LexicalEnvironment 참조 복사
  5. 변수 inner에 함수 할당
  6. inner 함수 실행.
    outer 컨텍스트 잠시 중단되고 inner 컨텍스트 활성화
  7. inner 컨텍스트의 environmentRecord에 {a} 저장
    outerEnvironmentReference에 outer 컨텍스트의 LexicalEnvironment참조 복사
  8. 변수 a를 조회 environmentRecord에 저장된 내용이 있지만 값이 할당되지 않아서 undefined 출력.
  9. a에 3 할당 (inner 함수 내부에서 선언된 변수)
  10. inner 함수가 종료되었으므로 inner 컨텍스트가 콜 스택에서 제거 outer 컨텍스트 활성화
  11. outer 컨텍스트의 outerEnvironmentReference에 a에 대한 내용이 있으므로 1 출력
  12. outer 컨텍스트 콜 스택에서 제거
  13. 전역 컨텍스트의 environmentRecord에 a에 대한 내용이 있으므로 1 출력
  14. 전역 컨텍스트 콜 스택에서 제거

thisBinding

this로 지정된 객체가 저장된다. 실행 컨텍스트 활성화 당시 this가 저장되지 않은 경우 전역 객체가 저장된다.


profile
소개소개~

0개의 댓글