이 파트는 원래 23장을 설명할 때 서술했지만, 생각보다 양이 많아지고 글의 포커스가 난잡해져서 분리하여 서술합니다 😉
우리, 저번 파트에서 렉시컬의 의미를 이해했어요!
따라서 우리는 이제 렉시컬이라는 말이 들어왔을 때, 가슴이 철렁! 내려앉을 필요가 없다구요 😉
렉시컬 환경이라하면 결국, 의미 분석을 위한 환경이겠죠?
따라서 의미 분석에 유용한 것들을 포함하게 돼요!
즉 렉시컬 환경은 말만 어렵지, 실제로는 스코프와 식별자를 관리한다! 끝입니다! 😆
그리고 이러한 렉시컬 환경은 환경 레코드, 외부 렉시컬 환경 참조로 나뉘게 됩니다.
그럼, 렉시컬 환경의 요소인 환경 레코드에 대해 살펴볼까요?
환경 레코드란, ECMAScript
정의에 따르면 다음과 같은 정의를 갖고 있답니다.
대개 환경 레코드는
함수 선언
,블록문
, 또는try/catch
와 같은ECMAScript
코드의 구체적인 어휘구조와 관련되어 있다. 이러한 코드들이 평가되고, 새로운 환경 레코드가 코드에 의해 생성된 식별자 바인딩을 기록하기 위해 생성된다.
즉, "식별자 바인딩 기록"에 초점이 맞춰진 거죠!
이때 이 환경 레코드는 [[OuterEnv]]
라는 내부 슬롯을 갖고 있는데, 이 내부 슬롯에서는 상위 환경 레코드 참조값, 혹은 null
값이 들어있다고 해요.
즉, 환경 레코드 역시 상위 환경 레코드가 감싸는 형태로 구성되어 있다는 사실을 알 수 있군요!
환경 레코드 계층 구조는 ECMA-262 원문을 참고하면서 기록해요!
환경 레코드는 다음과 같은 계층 구조를 갖고 있다고 해요!
선언적 환경 레코드는 직접적으로 식별자 바인딩을 하는, 어휘적 요소들의 결과를 정의해줘요.
따라서 다음과 같은 상황에서 사용이 됩니다!
var
let
const
class
module
import
funciton
(함수 선언)catch clause
(try / catch문의 catch)그중 하위 레코드인 함수 환경 레코드는 함수 객체의 호출에 해당하며, 함수에 대한 최상위 선언에 바인딩해주는 역할을 담당해줘요! (그것이 바로 this
바인딩입니다!) 또한, super
을 참조하고 있다면 super
메서드 호출에 필요한 상태들을 지원해줍니다.
나머지 하위 레코드인 모듈 환경 레코드는 외부 모듈의 범위를 나타내줍니다. 변경 가능한/불변하는 바인딩과 더불어, 다른 환경 레코드에 위치한 타겟 바인딩을 간접적으로 접근할 수 있도록 제공하기 위해 immutable import binding
을 제공한다고 하네요!
객체 환경 레코드는 바인딩 객체와 연관이 있어요!
바인딩 객체는 프로퍼티 이름에 해당하는 문자 식별자를 바인딩하는 역할을 해줍니다.
이때, 자신의 것과, 상속된 프로퍼티들이 모두 바인딩이 돼요.
가장 바깥의 스코프를 나타내기 위한 환경 레코드에요!
공통의 realm
(자바스크립트의 모든 코드들은 평가 전에 realm
에 연결돼요!)을 처리하는 모든 ECMAScript
Script
에 의해 공유됩니다.
이 친구는 빌트인 함수들과 전역 객체의 프로퍼티, Script
에서 발생한 최상단의 선언들을 바인딩해주는 역할을 해줍니다!
전역 환경 레코드는 논리적으로는 단일 객체지만, 실질적으로는 선언적 환경 레코드와 객체 환경 레코드를 감싸고 있다고 해요! 이때, 객체 환경 레코드는 연결된 Realm 레코드의 전역 객체를 기본 객체로 가지게 되고,
var
을 통한 변수 선언을 바인딩해줍니다.
이외의 선언 코드들은 전역 환경 레코드의 선언적 환경 레코드가 처리를 해준다고 하네요!😉
이제, 왜 전역 코드에서
var
가 암묵적 전역이 되는지를 이해할 수 있겠죠!
var
은 전역 환경 레코드에서 객체 환경 레코드가 담당하게 되는데, 이때var
을 통한 변수 선언 역시 프로퍼티로 바인딩하는 겁니다. (이것이window.x
가x
처럼 선언해도 이상이 없는 이유죠!)
후, 확실히 이 파트를 분리하니까 속이 후련하군요.
환경 레코드라는 걸 제대로 이해할 수 있어야, 비로소 실행 컨텍스트의 세밀한 부분에 대해 좀 더 이해를 할 수 있는 거 같아요.
덕분에 시간이 정말 많이 걸렸지만, 보람은 있네요. 이상! 🎉