Execution Context [5] - Scope Chain의 실체

Marullo·2021년 4월 8일
0
post-thumbnail

Intro

지금까지 실행 컨텍스트에 담기는 정보를 알아봤습니다.
실행 컨텍스트에는 함수 바로 바깥의 Scope와 내부 Scope만이 저장되는데,
우리는 JS에서 몇 단계 바깥에 있는 변수를 사용 가능하다는 것을 알고 있습니다.

예시를 들어보겠습니다.

function outter(){
  let outVar = 1000
  
  function inner(){
    let inVar = 100
    
    function getter(){
      let myVar = 10
      console.log(myVar, inVar) //=> 10, 100
      console.log(outVar)       //=> 1000
    }
    getter()
  }
  inner()
}
outter()

getter() 함수의 Function Object가 생성될 때, getter Function Object의 내부 프로퍼티[[Scope]]는 오직 inner함수의 영역입니다. 즉, 외부 렉시컬 참조에는 inVar 만 담겨있기 때문에 getter()의 console.log(outVar)는 식별자해결이 안되어 undefined가 떠야됩니다. 그런데 1000이 정확히 출력되는 것을 우리는 경험상 알고 있습니다.

이 경험들이 가능했던 이유는 바로 Scope를 참조하기 때문입니다.




JS Engine과 Scope Chain

getter가 inner의 변수인 inVar를 사용할 수 있는 이유는,
"getter 실행 컨텍스트"의 외부 렉시컬 참조가 inner의 Scope를 가리키고 있기 때문입니다.


JS Engine의 식별자 해결(Identifier Resolution)

먼저, 선언적 환경 레코드를 뒤집니다.(내 Scope를 뒤진다.)
만약, 내 Scope에서 변수 이름을 찾지 못했다면, 외부 렉시컬 참조를 뒤집니다. (바로 바깥의 Scope를 뒤진다.)

여기서도 변수 이름을 찾지 못했다면?? 외부 렉시컬 참조를 갈아끼웁니다.
외부 렉시컬 참조로 참조하는 대상을, "현재 참조하는 Scope의" 부모 Scope로 교체합니다.

외부 Scope에서 IR(식별자 해결)을 해결 못하면, 계속 현재 참조하는 Scope의 부모 Scope로 교체하는데, 이것을 Global Scope(보통 Window)까지 갈아끼웁니다.
Window까지 가서도 IR을 못하면 그제서야 undefined를 들고 오는 것입니다.




실체

Scope Chain은 식별자 해결시, 변수를 찾지 못하면 렉시컬 참조영역을 갈아끼우는 것을 의미합니다.
Scope Chain이라는 거창한 동작이 따로 있는 것이 아니라, 위에 설명된 엔진의 동작을 표현할 뿐입니다.

Scope 또한 다르지 않습니다. 변수들은 실행 컨텍스트에서 "최초의 외부 렉시컬 참조영역"과 "선언적 환경 레코드"에 저장됩니다.
Scope는 변수에 대해 IR을 진행할 수 있는 영역을 지칭할 뿐입니다.


profile
한국외대 중국어&컴공 복수전공 - 세미 전공자의 기술 블로그

0개의 댓글