자바스크립트의 실행 컨텍스트와 클로저

자바스크립트 엔진은 실행 컨텍스트를 통해 식별자와 스코프를 관리한다.

  • 실행 컨텍스트는 소스코드를 평가/실행하고 코드 실행 결과를 관리하는 영역이다.

  • 실행 컨텍스트는 식별자와 스코프를 관리(렉시컬 환경)하고, 코드 실행 순서를 관리(실행 컨텍스트 스택)하는 내부 메커니즘이다.

자바스크립트 엔진은 소스코드를 평가와 실행 두 단계로 나누어 처리한다.

  1. 소스코드 평가 단계: 선언문을 처리하고 평가 결과를 스코프에 등록

  2. 소스코드 실행 단계: 선언문을 제외한 코드를 실행. 실행에 필요한 정보(변수나 함수의 참조)를 실행 컨텍스트에서 확인하고, 변수 값 변경 등 실행 결과는 다시 실행 컨텍스트가 관리하는 스코프에 등록

렉시컬 환경

렉시컬 환경은 식별자가 선언된 위치에 따라 변수와 함수가 어떻게 접근되고 관리되는지를 정의한다. 식별자와 식별자에 바인딩된 값, 상위 스코프에 대한 참조를 기록하는 키-값 형태의 객체로 관리된다.

구성요소

  • 환경 레코드: 식별자와 값 관리

  • 외부 렉시컬 환경에 대한 참조: 상위 스코프에 대한 참조

→ 외부 렉시컬 환경에 대한 참조를 통해 단방향 링크드 리스트인 스코프 체인이 구현된다.

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

→ 외부 함수보다 중첩 함수가 더 오래 유지되는 경우 중첩 함수(클로저)는 이미 생명주기가 종료된 외부 함수의 변수를 참조할 수 있다.