자바스크립트의 실행 컨텍스트와 클로저
자바스크립트 엔진은 실행 컨텍스트를 통해 식별자와 스코프를 관리한다.
실행 컨텍스트는 소스코드를 평가/실행하고 코드 실행 결과를 관리하는 영역이다.
실행 컨텍스트는 식별자와 스코프를 관리(렉시컬 환경)하고, 코드 실행 순서를 관리(실행 컨텍스트 스택)하는 내부 메커니즘이다.
자바스크립트 엔진은 소스코드를 평가와 실행 두 단계로 나누어 처리한다.
소스코드 평가 단계: 선언문을 처리하고 평가 결과를 스코프에 등록
소스코드 실행 단계: 선언문을 제외한 코드를 실행. 실행에 필요한 정보(변수나 함수의 참조)를 실행 컨텍스트에서 확인하고, 변수 값 변경 등 실행 결과는 다시 실행 컨텍스트가 관리하는 스코프에 등록
렉시컬 환경
렉시컬 환경은 식별자가 선언된 위치에 따라 변수와 함수가 어떻게 접근되고 관리되는지를 정의한다. 식별자와 식별자에 바인딩된 값, 상위 스코프에 대한 참조를 기록하는 키-값 형태의 객체로 관리된다.
구성요소
환경 레코드: 식별자와 값 관리
외부 렉시컬 환경에 대한 참조: 상위 스코프에 대한 참조
→ 외부 렉시컬 환경에 대한 참조를 통해 단방향 링크드 리스트인 스코프 체인이 구현된다.
const x = 0;
function outer() {
const y = 1;
function inner() {
const z = 2;
}
}
위와 같은 코드에서 함수 inner()
는 중첩함수, outer()
는 외부함수 라고 한다.
이를 스코프 체인으로 나타내면 아래와 같다.
변수 참조시 해당 코드의 스코프에서 부터 상위 스코프 방향으로 변수를 검색한다.
클로저
렉시컬 환경을 이해하면 클로저도 이해할 수 있다.
클로저는 함수와 상위 스코프(그 함수가 선언된 렉시컬 환경)와의 조합이다. 함수는 자신의 내부 슬롯 [[Environment]]
에 자신이 정의된 환경인 상위 스코프에 대한 참조를 저장한다. 따라서 외부 함수의 생명주기가 종료되어도 중첩 함수는 외부 함수의 변수를 참조할 수 있다. 이러한 중첩 함수를 클로저라고 부른다.
const x = 1;
function outer() {
const x = 10;
const inner = function () {
console.log(x);
};
return inner;
}
const innerFunc = outer();
innerFunc(); // 10
→ 외부 함수보다 중첩 함수가 더 오래 유지되는 경우 중첩 함수(클로저)는 이미 생명주기가 종료된 외부 함수의 변수를 참조할 수 있다.