Javascript 클로저(Closure)의 개념 및 유용한 사용 예
Code/JavaScript

Javascript 클로저(Closure)의 개념 및 유용한 사용 예

반응형

클로저 (Closure) : 외부함수의 변수에 접근할 수 있는 내부 함수 또는, 이러한 작동원리를 일컫는 용어

정확한 정의는, 함수와 함수를 둘러싼 어휘적 환경의 조합

 

function outerFn() {
  let outerVar = 'outer';
  console.log(outerVar);

  function innerFn() {
    let innerVar = 'inner';
    console.log(innerVar);
  }
}

let globarVar = 'golbal'f;
outerFn();

 

위 코드에서 inner 함수에서 접근 할 수 있는 Scope는 총 3개이다.

 

inner 함수에서 접근 가능한 Scope

 

 

함수의 리턴

function outerFn() {
  let outerVar = 'outer';
  console.log(outerVar);

  function innerFn() {
    let innerVar = 'inner';
    console.log(innerVar);
  }
  return innerFn;
}

outerFn();

 

 

콘솔에 outreVar 의 값이 찍히고, 아직 실행되지 않은 함수 (innerFn) 의 정보가 리턴되는 것을 확인 할 수 있다.

 

function outerFn() {
  let outerVar = 'outer';
  console.log(outerVar);

  function innerFn() {
    let innerVar = 'inner';
    console.log(innerVar);
  }
  return innerFn;
}

outerFn()();             // 외부함수와 내부 함수를 연달아 호출
let innerFn = outerFn(); // 외부함수의 리턴값을 innerFn이라는 변수에 담는다
innerFn();               // 내부 함수가 담긴 innerFn을 호출

 

위의 코드를 콘솔로 작동해보면 좀 더 빠른 이해가 가능할 것이다.

 

여기서 innerFn 함수는 클로저 함수라고 볼 수 있다.

 

클로저 함수 안에서는

- 지역 변수 (innerVar)

- 외부 함수의 변수(outerVar)

- 전역 변수(golbalVar)의 접근이 전부 가능

 

 

그렇다면, 유용한 클로저 사용 예를 알아보자.

커링 : 함수 하나가 n개의 인자를 받는 대신, n개의 함수를 만들어 각각 인자를 받게 하는 방법

function adder(x) {
  return function(y) {
    return x + y;
  }
}

adder(2)(3); // 5

let add100 = adder(100); // x의 값을 고정해놓고 재사용할 수 있다.
add100(2);  // 102
add100(10); // 110

let add5 = adder(5);
add5(2);    // 7

 

아래와 같이, 외부함수의 변수가 저장되어 마치 템플릿 함수와 같이 사용하는 것도 가능하다.

 

function htmlMaker(tag) {
  let startTag = '<' + tag + '>';
  let endTag = '</' + tag + '>';
  return function(content) {
    return startTag + content + endTag;
  }
}

let divMaker = htmlMaker('div');
divMaker('code');   // <div>code</div>
divMaker('states'); // <div>states</div>

let h1Maker = htmlMaker('h1');
h1Maker('Headline'); // <h1>Headline</h1>

 

클로저 모듈 패턴 : 변수를 스코프 안쪽에 가두어 함수 밖으로 노출 시키지 않는 방법

function makeCounter() {
  let privateCounter = 0;

  return {
    increment: function() {
      privateCounter++;
    },
    decrement: function() {
      privateCounter--;
    },
    getValue: function() {
      return privateCounter;
    }
  }
}

let counter1 = makeCounter();
counter1.increment();
counter1.increment();
counter1.getValue(); // 2

let counter2 = makeCounter();
counter2.increment();
counter2.decrement();
counter2.increment();
counter2.getValue(); // 1

 

두 카운터에 각기 다른 privateCounter를 다루면서, privateCounter를 밖으로 노출시키지 않을 수 있다.

 

 

반응형