클로저(closure)

succeeding·2022년 6월 17일
0

JavaScript 베이스

목록 보기
6/6

클로저(closure)란?

외부 변수를 기억하고 이 외부 변수에 접근할 수 있는 함수

  • 몇몇 언어에서는 클로저를 구현하는 게 불가능하거나 특수한 방식으로 함수를 작성해야 클로저를 만들 수 있음
  • JS에선 모든 함수가 자연스럽게 클로저가 됨
    • lexical environment와 [[Environment]] 프로퍼티를 통해 클로저로 동작

렉시컬 환경(Lexical Environment)

내부 숨김 연관 객체(internal hidden associated object)로써 다음 두 부분으로 구성

  • 환경 레코드(Environment Record) - 모든 지역 변수를 프로퍼티로 저장하고 있는 객체
    • 변수나 함수는 특수 내부 객체인 환경 레코드의 프로퍼티일 뿐임
      • 변수를 가져오거나 변경하는 것환경 레코드의 프로퍼티를 가져오거나 변경함을 의미
  • 외부 렉시컬 환경에 대한 참조

동작 방식

  1. 스크립트 실행시 스크립터 전체와 관련된 전역 렉시컬 환경 생성

    • 변수는 선언문 전까지 <uninitialized> 값을 가지며 이 때는 참조될 수 없음
    • 함수는 선언문으로 표현된 경우 즉시 초기화되어 사용가능하고 표현식으로 표현된 경우는 바로 사용 불가
    • 외부 렉시컬 환경에 대한 참조는 null
  2. 함수 호출 시 함수의 렉시컬 환경 생성

    • 외부 렉시컬 환경에 대한 참조는 함수를 호출한 곳의 렉시컬 환경
  3. 코드에서 변수에 접근할 땐, 먼저 내부 렉시컬 환경 -> 외부 렉시컬 환경 -> ... -> 전역 렉시컬 환경

[[Environment]]

모든 함수가 갖는 숨김 프로퍼티이며, 여기에 함수가 만들어진 곳의 lexical environment에 대한 참조가 저장되며 영원히 변하지 않음

[[Environment]] 프로퍼티를 통해 함수는 계속해서 같은 외부 렉시컬 환경에 접근하여 같은 외부 변수에 접근할 수 있다. 즉, 클로저 함수가 구현된 것.

예시

function makeCounter() {
  let count = 0;

  return function() {
    return count++;
  };
}

let counter = makeCounter();

alert( counter() ); // 0
alert( counter() ); // 1
alert( counter() ); // 2

중첩함수로 정의된 counter는 실행할 때마다 외부 변수인 count에 접근하여 그 값을 +1 한다. 이 때 counter()로 호출할 때마다 새로운 렉시컬 환경이 생성되는데 [[Environment]]프로퍼티에 저장되어 있는 외부 렉시컬환경 참조를 기억하여 계속해서 같은 외부 렉시컬 환경에 접근할 수 있고, 그를 통해 count 값이 계속해서 증가할 수 있는 것.

참고 자료

JAVASCRIPT.INFO - 변수의 유효 범위와 클로저

0개의 댓글