JavaScript | 클로저(Closures)

yuni·2022년 11월 25일
0

javascript

목록 보기
16/16
post-thumbnail

⬆ 클로저(Closure)

⇨ 클로저는 반환된 내부함수가 자신이 선언됐을 때의 환경(Lexical environment)인 스코프를 기억하여 자신이 선언됐을 때의 환경(스코프) 밖에서 호출되어도 그 환경(스코프)에 접근할 수 있는 함수를 말한다.(=내부함수에서 외부함수의 상태에 접근할수있는 권한을 준다.)

function outerFunc() {
  let x = 10;
  let innerFunc = function () { console.log(x); };
  return innerFunc;
}

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

클로저에 의해 참조되는 외부함수의 변수 즉 outerFunc 함수의 변수 x를 자유변수(Free variable)라고 부른다. 클로저라는 이름은 자유변수에 함수가 닫혀있다(closed)라는 의미로 의역하면 자유변수에 엮여있는 함수라는 뜻이다.

❗ 클로저 활용

- 캡슐화와 정보의 은닉

클로저의 특징을 사용해 클래스 기반 언어의 private 키워드를 흉내낼 수 있다.

function Counter() {
  // 카운트를 유지하기 위한 자유 변수
  let 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

//클래스버전
class Counter {
  #count = 0;
  increase() {
    this.#count++;
    console.log(this.#count);
  }
  decrease() {
    this.#count--;
    console.log(this.#count);
  }
}
const counter = new Counter();
counter.increase(); //1
counter.increase(); //2
counter.decrease(); //1

생성자 함수 Counter의 변수 counter는 this에 바인딩된 프로퍼티가 아니라 변수이기때문에, 생성자 함수 Counter 내에서 선언된 변수 counter는 생성자 함수 Counter 외부에서 접근할 수 없다. 하지만 생성자 함수 Counter가 생성한 인스턴스의 메소드인 increase, decrease는 클로저이기 때문에 자신이 생성됐을 때의 렉시컬 환경인 생성자 함수 Counter의 변수 counter에 접근할 수 있다. 이러한 클로저의 특징을 사용해 클래스 기반 언어의 private 키워드를 흉내낼 수 있다.

    let makeCounter = function() {
      //private
      let privateCounter = 0;
      //private
      function changeBy(val) {
        privateCounter += val;
      }
      
      return {
        increment: function() {
          changeBy(1);
        },
        decrement: function() {
          changeBy(-1);
        },
        value: function() {
          return privateCounter;
        }
      }
    };

    let counter1 = makeCounter();
    let counter2 = makeCounter();
    alert(counter1.value()); /* 0 */
    counter1.increment();
    counter1.increment();
    alert(counter1.value()); /* 2 */
    counter1.decrement();
    alert(counter1.value()); /* 1 */
    alert(counter2.value()); /* 0 */

변수 privateCounter과 함수 changeBy는 외부에서 접근이 불가능하다.
increment, decrement, value만이 외부에서 접근이 가능하다.

참고 및 출처
클로저 - MDN
클로저 - poiemaweb

profile
˗ˋˏϟˎˊ˗ 개발 지식 쌓기

0개의 댓글