[JS] 스코프 체인, outerEnvironmentReference

cabbage·2023년 4월 13일

JS

목록 보기
28/43
post-thumbnail

저번 주제로 작성했던 environmentRecord와 호이스팅에 이어서 실행 컨텍스트를 구성하는 LexicalEnvironment의 outerEnvironmentReference(outer 참조)와 스코프 체인에 대해 작성한다.

LexicalEnvironment

저번 주제에서 작성했던 대로 LexicalEnvironment는 실행 컨텍스트의 구성 요소 중 하나로, 실행 컨텍스트를 구성하는 환경 정보들을 모아놓은 것이다. 그리고 LexicalEnvironment는 2개의 구성 요소를 갖는다.

  • environmentRecord
  • outerEnvironmentReference(outer 참조)

environmentRecord는 식별자 관련 정보를 저장한다. 이번 주제인 outer 참조는 외부 LexicalEnvironment를 참조하는 포인터이다.

스코프 체인

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

스코프 체인이란 현재 스코프에서 식별자를 검색할 때 상위 스코프를 연쇄적으로 찾아가는 방식을 말한다.

어떤 함수가 호출되어 함수 실행 컨텍스트가 생성될 때 함수 실행 컨텍스트의 구성 요소인 LexicalEnvironment가 만들어진다. 그리고 LexicalEnvironment는 내부에 outer 참조를 갖는다.

outer 참조는 호출된 함수가 선언된 시점의 LexicalEnvironment를 참조한다. 호출된 함수가 선언된 시점의 LexicalEnvironment는 상위 스코프를 의미한다. 즉 outer 참조는 상위 스코프의 LexicalEnvironment를 참조한다.

outer 참조는 상위 스코프의 LexicalEnvironment를 참조하므로 스코프가 체인처럼 연결된다. 즉 outer 참조를 통해 스코프 체인이 구성된다.

스코프 체인 구성 예시

  1. 함수 A를 글로벌 스코프에 선언한다.
  2. 함수 A 내부에 함수 B를 선언한다.
  3. 함수 B 내부에 함수 C를 선언한다.
  • 함수 C의 outer 참조는 함수 B 실행 컨텍스트의 LexicalEnvironment를 참조한다.
  • 함수 B의 outer 참조는 함수 A 실행 컨텍스트의 LexicalEnvironment를 참조한다.
  • 함수 A의 outer 참조는 글로벌 실행 컨텍스트의 LexicalEnvironment를 참조한다.

함수 C에서 접근하는 식별자를 스코프 체인에서 검색하는 과정 예시

  1. 함수 C가 호출되어 함수 C 실행 컨텍스트가 생성된다. 함수 C 실행 컨텍스트의 LexicalEnvironment의 environmentRecord에서 식별자를 검색한다.
  2. 자신의 environmentRecord에서 식별자를 찾지 못하면 outer 참조가 가리키는 함수 B 실행 컨텍스트 LexicalEnvironment의 environmentRecord에서 식별자를 검색한다.
  3. 함수 B의 environmentRecord에서 식별자를 찾지 못하면 함수 B의 outer 참조가 가리키는 함수 A 실행 컨텍스트 LexicalEnvironment의 environmentRecord에서 식별자를 검색한다.
  4. 함수 A의 environmentRecord에서 식별자를 찾지 못하면 함수 A의 outer 참조가 가리키는 글로벌 실행 컨텍스트 LexicalEnvironment의 environmentRecord에서 식별자를 검색한다.

outer 참조는 연결리스트의 형태를 띄게 되어 함수 선언 시점의 LexicalEnvironment를 계속 따라가면 결국 마지막엔 글로벌 실행 컨텍스트의 LexicalEnvironment가 나온다.

outer 참조는 오직 함수 선언 시점의 LexicalEnvironment만 참조하므로 가장 가까운 LexicalEnvironment부터 차례대로 접근할 수 있고 다른 순서로 접근할 수 없다. 이런 구조적 특성 때문에 여러 스코프에서 동일한 식별자를 선언한 경우 무조건 스코프 체인 상에서 가장 먼저 발견된 식별자에만 접근할 수 있다.

var d = 'd';

function a () {
  var a = 'a';
  function b () {
    var a = 'aa';
    function c () {
      console.log(a);  // 1️⃣ 'aa'
      console.log(d);  // 2️⃣ 'd'
    }
    c();
  }
  b();
}
a();

1️⃣ - 함수 c 내부에서 변수 a에 접근하는 경우 함수 a 내부에도 변수 a가 선언되어 있지만 함수 b 내부에서 선언된 변수 a에만 접근할 수 있다.
2️⃣ - 함수 c 내부에서 변수 d에 접근하는 경우 먼저 함수 c의 environmentRecord를 탐색한다. 변수 d를 찾지 못하면 스코프 체인을 따라 함수 b, a 그리고 글로벌의 environmentRecord를 차례로 탐색한다.

정리

  • outer 참조는 함수 선언 시점의 LexicalEnvironment(상위 스코프의 LexicalEnvironment)를 참조한다.
  • 어떤 변수에 접근하는 경우 현재 활성화된 실행 컨텍스트의 LexicalEnvironment의 environmentRecord에서 변수 정보를 탐색하여 변수 정보가 발견되면 그 값을 반환하고, 발견하지 못하면 outer 참조가 참조하는 상위 스코프의 LexicalEnvironment를 재탐색한다.
  • 글로벌 실행 컨텍스트의 LexicalEnvironment까지 탐색해도 변수를 찾지 못하면 undefined를 반환한다.

참조

  • 코어 자바스크립트 - 정재남
profile
캐비지 개발 블로그입니다. :)

0개의 댓글