Chapter 24 클로저

Closures

  • 오 프언 리뷰느낌쓰,,
  • JS 한정이 아니기에 ECMAScript 에 등장 X

Closure = function + lexical environment of function (when declared) - MDN

24.1 렉시컬 스코프

  • recap
    • JS Engine: 어디서 호출이 아닌, 어디에 정의되었는지에 따라 상위 스코프 결정
    • \(\rightarrow\) 정적 스코핑 (lexical/static scoping)

24.2 함수 객체의 내부 슬롯 [[Environment]]

  • 함수 객체가 생성될 때, 함수가 정의된 환경[[Environment]] 내부 슬롯에 저장
    • => 상위 스코프를 여기다 저장함
    • => 상위 스코프 참조 = 현재 실행 중인 실행 컨텍스트의 렉시컬 환경, because 생성 시점에는 상위 함수가 평가/실행중이기 때문

24.3 클로저와 렉시컬 환경

const x = 1;

function outer() {
  const x = 10;
  const inner = function () {
    console.log(x); // 평가식이기에 runtime에 실행됨
  };
  return inner;
}

const innerFunc = outer();
innerFunc(); // 10
  • outerinner를 반환하고 (life cycle) 종료

    • outer의 실행 컨텍스트는 스택에서 pop
    • x 역시 생명주기 마감
  • BUT, inner은 어떻게 x 접근 가능한가?

    • outer의 렉시컬 환경을 기억하고 있음
    • inner가 호출되면, outer의 렉시컬 환경을 참조하여 x를 찾음
  • 📌 외부함수보다 중첩함수가 더 오래 유지되는 경우

    • 중첨함수는 이미 생명주기가 종료된 외부함수의 변수에 접근 가능
    • 이러한 중첩함수를 클로저라고 부름
  • WHY?

    • 위 실행 컨텍스트가 스택에서 pop 되지만 환경까지 소멸되는 것은 아님!
    • inner[[Environment]]에 의해 참조 -> GC 대상 X
  • 이론적으로 JS의 모든 함수는 클로저지만, 딱히 그렇게 부르진 않음

CASES::

  1. 상위 스코프의 어떤 식별자도 참조하지 않는 함수는 클로저라고 부르지 않는다
  • modern JS 는 최적화를 통해 상위스코프를 기억하지 않음 (메모리 관리)
  1. 외부함수보다 생명주기가 짧은 중첩함수는 클로저라고 하지 않는다
  • 외부함수가 종료되면, 중첩함수도 종료되기 때문

  • 클로저의 경우, 상위 스코프 중의 참조하고 있는 식별자만을 기억하는 것이 대부분 (최적화)

  • 자유 변수 (free variable): 클로저가 기억하는 상위 스코프의 변수

    • 클로저란, 함수가 자유 변수에 대해 닫혀있는 것
    • aka, 자유 변수에 묶여있는 함수

24.4 클로저의 활용

  • 클로저: 상태를 안전하게 변경하고 유지하기 위해 사용
    • 상태를 안전하게 은닉 (information hiding)
    • 특정 함수에게만 상태 변경 권한 부여