렉시컬 환경에 대해 알아보도록 하겠습니다.
렉시컬 환경 개념
렉시컬 환경이란, 실행 컨텍스트를 구성하는 컴포넌트입니다. 렉시컬 환경은 식별자와 식별자에 바인딩된 값. 상위 스코프에 대한 참조를 기록하고 저장해두는 저장소의 개념이라 생각하시면 되겠습니다.
추가로 설명하면, 코드 block, function, script를 실행하기 전에! 생성되는 객체입니다. 실행할 스코프 범위 안에 있는 변수와 함수를 프로퍼티로 저장하는 객체입니다.
앞전에 살펴봤던 실행 컨텍스트 스택은 코드의 실행순서를 관리했다면, 렉시컬 환경은 스코프를 구별하여 식별자를 등록, 관리하는 친구구나! 라고 생각하시면 되겠습니다.
렉시컬 환경 구성요소
첫 번째, 환경레코드 입니다.
환경 레코드는 스코프에 포함된 식별자를 등록하고 등록한 식별자에 바인딩 된 값을 관리하는 저장소입니다. 환경 레코드는 소스코드의 타입에 따라 관리하는 내용에 차이가 있습니다.
두 번째, 외부 렉시컬 환경에 대한 참조 입니다.
외부 렉시컬 환경에 대한 참조는 상위 스코프를 가르킵니다. 이때 상위 스코프는 외부 렉시컬 환경, 즉 해다 실행 컨텍스트를 생성한 소스코드를 포함하는 상위 코드의 렉시컬 환경을 말합니다. 외부 렉시컬 환경에 대한 참조를 통해 단방향 링크드 리스트인 스코프 체인을 구현합니다.
외부 렉시컬 환경은 코드를 실행할 때 필요한 변수를 해당 로컬 스코프와 연관돼 있는 활경 레코드를 먼저 찾고, 없다면 렉시컬 환경이 갖고 있는 외부 렉시컬 환경에 대한 참조로 접근해서 탐색합니다. 만약 글로벌 렉시컬 환경까지 도달했을 때까지 찾는 식별자가 없다면 에러를 반환합니다.
렉시컬 환경의 작동 방식
전역코드가 시작되면 렉시컬 환경 객체가 만들어집니다. 코드 실행 전에 선언되어 있는 변수와 함수를 글로벌 환경 레코드에 저장합니다.
여기서 선언방식에 따라 저장방식에도 차이가 있습니다.
var 로 선언된 변수
환경레코드에 최초로 변수를 저장할때 변수 이름은 key로 설정하고, value에 undefined로 초기화합니다. 소스코드가 평가될때 환경레코드에 선언문이 먼저 실행된다고 말씀드렸던 부분입니다. 때문에 변수가 선언되기전에 참조하려했을 때, 참조에러가 발생하지않고 undefined를 가져오게됩니다.
let, const 로 선언된 변수
let과 const 로 선언된 경우, 환경레코드에 변수 이름은 key로 설정하고 value에는 uninitialized 라는 상태로 초기화 합니다. 위에 var의 경우 undefined로 설정했는데 let과 const는 초기화단계부터 다릅니다. uninitialized는 undefined와는 다ㄹ게 참조할 수 없는 값입니다. 때문에 선언전에 해당 변수의 값을 참조하려한다면 참조에러가 발생하게 됩니다.
let a = 1;
function referenceError () {
console.log(a);
let a = 2;
}
referenceError();
위 코드에서 referenceError 함수를 실행시키면 console.log(a)는 어떤 값을 참조할까요?
정답은 지역 스코프에 담긴 let a = 2; 입니다.
함수 평가 단계에서 환경레코드에 키값을 a로 지정하고 value값은 uninitialized로 초기화 하게 됩니다. console.log(a)를 실행할 단계에서는 지역스코프에서 a를 찾게 되고, a의 값은 참조할 수 없는 uninitialized가 됨으로 참조에러가 발생하게 됩니다.
또 하나의 케이스를 보겠습니다.
함수가 선언식으로 선언된 경우 함수 이름을 key값으로 함수 자체를 value로 저장하여 완전한 상태로 초기화 합니다. var로 선언된 변수는 선언 전에 참조하려하면 undefined를 리턴하는 반면, 함수 선언식은 초기화 될때 완전하게 저장되기 때문에 선언 전에 접근하더라도 문제없이 사용할 수 있습니다.
console.log(sum(1,2)); // 3
function sum (a,b) {
return a + b
}
console.log(add(1,2)); // Uncaught TypeError: sum is not a function
var sum = function(a,b) {
return a + b
}
console.log(sum); // undefined
var sum = function(a,b) {
return a + b
}
'JavaScript' 카테고리의 다른 글
[JS] 실행 컨텍스트 뿌수기 #4 객체지향프로그래밍(OOP) (0) | 2024.03.04 |
---|---|
[JS] 실행 컨텍스트 뿌수기 #3 함수 (0) | 2024.02.29 |
[JS] 실행 컨텍스트 뿌수기 #1 소스코드 (0) | 2024.02.28 |
[JS] Scope chaning (0) | 2024.02.20 |
[JS] 배열 비교 (0) | 2024.01.13 |