본문 바로가기
JavaScript

[JavaScript] 클로저 (closure)

by lvd-hy 2023. 3. 17.
반응형

 

목차

     

    클로저 (closure)

    함수와 그 함수가 선언된 렉시컬 환경과의 조합이다.

    🧐

    렉시컬 환경 (Lexical Environment)
    식별자와 식별자에 바인딩된 값, 그리고 상위 스코프에 대한 참조를 기록하는 자료구조로 실행 컨텍스트를 구성하는 컴포넌트이다.

     

    function outerFunc() {
      const x = 10;
      const innerFunc = function () { console.log(x); };
      return innerFunc;
    }
    
    /**
     *  함수 outerFunc를 호출하면 내부 함수 innerFunc가 반환된다.
     *  그리고 함수 outerFunc의 실행 컨텍스트는 소멸한다.
     */
    const inner = outerFunc();
    inner(); // 10

    - outerFunc 함수는 중첩 함수 innerFunc를 반환하고 생명 주기(life-cycle)를 마감한다.

    ➡️ outerFunc 함수의 실행이 종료되면 outerFunc 함수의 실행 컨텍스트는 실행 컨텍스트 스택에서 제거된다.

    - 함수 outerFunc는 실행된 이후 실행 컨텍스트 스택에서 제거되었으므로 함수 outerFunc의 변수 x 또한 더이상 유효하지 않게 되어 변수 x에 접근할 수 있는 방법은 달리 없어 보인다.

    - 그러나 위 코드의 실행 결과는 변수 x의 값인 10이다.

    이처럼 자신을 포함하고 있는 외부함수보다 내부함수가 더 오래 유지되는 경우, 외부 함수 밖에서 내부함수가 호출되더라도 외부함수의 지역 변수에 접근할 수 있는데 이러한 함수를 클로저(Closure)라고 부른다.

    클로저 (closure)의 활용

    상태 유지

    현재 상태를 기억하고 변경된 최신 상태를 유지

    현재 상태(위 예제의 경우 .box 요소의 표시 상태를 나타내는 isShow 변수)를 기억하고 이 상태가 변경되어도 최신 상태를 유지해야 하는 상황에 매우 유용하다. 

    전역 변수의 사용 억제

    // 함수를 인자로 전달받고 함수를 반환하는 고차 함수
    // 이 함수가 반환하는 함수는 클로저로서 카운트 상태를 유지하기 위한 자유 변수 counter을 기억한다.
    function makeCounter(predicate) {
      // 카운트 상태를 유지하기 위한 자유 변수
      var counter = 0;
      // 클로저를 반환
      return function () {
        counter = predicate(counter);
        return counter;
      };
    }
    
    // 보조 함수
    function increase(n) {
      return ++n;
    }
    
    // 보조 함수
    function decrease(n) {
      return --n;
    }
    
    // 함수로 함수를 생성한다.
    // makeCounter 함수는 보조 함수를 인자로 전달받아 함수를 반환한다
    const increaser = makeCounter(increase);
    console.log(increaser()); // 1
    console.log(increaser()); // 2
    
    // increaser 함수와는 별개의 독립된 렉시컬 환경을 갖기 때문에 카운터 상태가 연동하지 않는다.
    const decreaser = makeCounter(decrease);
    console.log(decreaser()); // -1
    console.log(decreaser()); // -2

    정보의 은닉

    function Counter() {
      // 카운트를 유지하기 위한 자유 변수
      var counter = 0;
    
      // 클로저
      this.increase = function () {
        return ++counter;
      };
    
      // 클로저
      this.decrease = function () {
        return --counter;
      };
    }
    
    const counter = new Counter();
    
    console.log(counter.increase()); // 1
    console.log(counter.decrease()); // 0

    - 생성자 함수 Counter의 변수 counter는 this에 바인딩된 프로퍼티가 아니라 변수다.

    - counter가 this에 바인딩된 프로퍼티라면 ?

    생성자 함수 Counter가 생성한 인스턴스를 통해 외부에서 접근이 가능한 public 프로퍼티가 되지만 생성자 함수 Counter 내에서 선언된 변수 counter는 생성자 함수 Counter 외부에서 접근할 수 없다.

    - 생성자 함수 Counter가 생성한 인스턴스의 메소드인 increase, decrease는 클로저이기 때문에 자신이 생성됐을 때의 렉시컬 환경인 생성자 함수 Counter의 변수 counter에 접근할 수 있다

    Reference

    https://developer.mozilla.org/ko/docs/Web/JavaScript/Closures

     

    클로저 - JavaScript | MDN

    클로저는 주변 상태(어휘적 환경)에 대한 참조와 함께 묶인(포함된) 함수의 조합입니다. 즉, 클로저는 내부 함수에서 외부 함수의 범위에 대한 접근을 제공합니다. JavaScript에서 클로저는 함수 생

    developer.mozilla.org

    모던 자바스크립트 딥다이브 24장

    https://poiemaweb.com/js-closure

     

    Closure | PoiemaWeb

    클로저(closure)는 자바스크립트에서 중요한 개념 중 하나로 자바스크립트에 관심을 가지고 있다면 한번쯤은 들어보았을 내용이다. execution context에 대한 사전 지식이 있으면 이해하기 어렵지 않

    poiemaweb.com

     

    반응형

    'JavaScript' 카테고리의 다른 글

    [JavaScript] 배열 고차 함수  (0) 2023.03.17
    [JavaScript] 스코프 예제로 이해하기  (0) 2023.03.17
    [JavaScript] 식별자 네이밍 규칙  (0) 2023.03.17
    [JavaScript] 프로토타입 체인  (0) 2023.03.16
    [JavaScript] Prototype  (0) 2023.03.15

    댓글