노트 #24 | 클로저

HyeonWooGa·2022년 7월 11일
0

노트

목록 보기
25/74

개요

JavaScipt에서는 다른 컴퓨터 언어와는 조금 다른 특성을 종종 가지고 있습니다. 그 중 종종 사용되는 클로저라는 개념이 있습니다.


학습 목표

  • 클로저 함수의 정의와 특징에 대해서 이해할 수 있다.
  • 클로저가 갖는 스코프 범위를 이해할 수 있다.
  • 클로저를 이용해 유용하게 쓰이는 몇 가지 패턴을 이해할 수 있다.

클로저(Closure) 개요

  • 함수와 함수가 선언된 어휘적 환경의 조합
    • 어휘적 환경의 조합 : 변수 및 함수 선언의 형태
  • 클로저 함수
    • 함수를 리턴하는 함수
    • 예시1 (화살표 함수)
      // 함수의 기본 형태
      
      const add = (x, y) => x + y;
      add(5, 7)  // 12
      
      // 클로져 함수, 함수의 호출이 두번 발생
      const adder = x => y => x + y;
      adder(5)(7);  // 12
      
      typeof adder(5)  // 'function'
      adder(5). // y => x + y
      • adder(5) 의 리턴 값이 함수입니다.
    • 예시2 (function 키워드 함수)
      // 예시1 의 adder와 동일한 함수
      
      const adder = function (x) {
        return function (y) {
          return x + y;
        }
      }
      • 리턴하는 함수에 의해 스코프(변수의 접근 범위)가 구분됩니다.
      • 변수 x 와 변수 y 는 선언된 곳이 각각 다릅니다.
      • 클로저의 핵심은 스코프를 이용해서 변수의 접근 범위를 닫는(closure;폐쇄)데에 있습니다.
        • 내부 함수는 x 에 접근이 가능합니다.
        • 외부 함수는 y 에 접근이 불가능합니다.

클로저의 기초활용 (데이터를 보존하는 함수)

  • 기본예시
    // 데이터를 보존하는 함수 예시
    
    const adder = function (x) {
      return function (y) {
        return x + y;
      }
    }
    
    const add5 = adder(5);
    add5(7);  // 12
    add5(10);  // 15
    • add5adder 함수에서 인자로 넘긴 5라는 값을 x 변수에 계속 담은 채로 남아있습니다!
  • 보다 실용적인 예시 : HTML 문자열 생성기
    // 실용적인 예시 : HTML 문자열 생성기
    
    const tagMaker = tag => content => `<${tag}>${content}</${tag}>`
    
    const divMaker = tagMaker('div');
    divMaker('hello');  // '<div>hello</div>'
    divMaker('world')  // '<div>world</div>'
    
    const anchorMaker = tagMker('a');
    anchorMaker('go')  // '<a>go</a>'
    anchorMaker('velog')  // '<a>velog</a>'
    • 클로저는 이처럼 특정 데이터를 스코프 안에 가두어 둔 채로 계속 사용할 수 있게 해줍니다.

클로저의 유용한 활용 (정보의 접근 제한, 캡슐화)

  • 클로저를 이용해 내부 함수를 객체에 담아 여러 개의 내부 함수를 리턴하도록 만듭니다.

  • 클로저 모듈 패턴 예시

    // 클로저 모듈 패턴 예시
    
    const makeCounter = () => {
      let value = 0;
    
      return {
        increase: () => {
          value = value + 1;
        },
        decrease: () => {
          value = value - 1;
        },
        getValue: () => value
      }
    }
    
    const counter1 = makeCounter();
    typeof counter1;  // 'object'
    counter1  // {increase: ƒ, decrease: ƒ, getValue: ƒ}
    • makeCounter 함수 내 value 는 직접 수정이 불가능하고 오직 리턴하는 객체가 제공하는 메서드(method)를 통해서 간접적으로 접근할 수 있습니다.
    • 위의 캡슐화(모듈화)를 통해서 변수 value 는 전역 변수가 선언될 필요가 없어졌습니다.
    • side effect 를 최소화 하며 오류로부터 보다 안전하게 값(value)을 보호할 수 있습니다.
  • 여러 개의 counter 를 만드는 것이 가능합니다.

    // 재활용 가능한 makeCounter 함수
    
    const counter1 = makeCounter();
    counter1.increase();
    counter1.increase();
    counter1.decrease();
    counter1.getValue();  // 1
    
    const counter2 = makeCounter();
    counter2.decrease();
    counter2.decrease();
    counter2.decrease();
    counter2.getValue();  // -3
    • counter1valuecounter2value 는 서로에게 영향을 끼치지 않고 각각의 값을 보존할 수 있습니다.

결론

  • 클로저를 통해 데이터와 메서드를 같이 묶어서 다룰 수 있습니다.
  • 클로저는 모듈화(캡슐화)에 유리합니다.
profile
Aim for the TOP, Developer

0개의 댓글