Closer

클로저란 외부 실행 컨택스트와 내부 실행 컨텍스트를 함께 쓸 수 있는 것이다. MDN에서는 함수와 그 함수가 선언 됐을 때의 렉시컬 환경과의 조합이다. 라고 설명한다. 여기서 중요한 것은 함수가 선언되었을 때의 렉시컬 환경이다. 렉시컬 환경이란 자바스크립트의 실행 컨텍스트의 정보중 하나인데 식별자와 스코프를 관리하는 환경 정보이다.

외부 함수에서 선언한 변수를 그 외부 함수의 내부 함수가 참조한 상태로 바깥으로 노출됐을 때, 실행 컨텍스트가 종료된 후에도 가비지 컬렉터의 대상이 되지 않는 현상을 클로저라고 한다.

(function () {
 var a = 0;
 var intervalId = null;

 var inner = function () {

  if (++a >= 10) {
   clearInterval(intervalId);
   inner = null; // 가비지 컬렉션의 대상이 될 수 있게 내부 함수가 참조하는 지역변수를 지워줌
  }

  console.log(a);
 };

 intervalId = setInterval(inner, 1000);
})();

클로저를 사용하게 되면 메모리 누수가 일어날 수 있다. 그렇다면 방지하는 방법은? 참조 카운터를 0으로 만들어주면 된다.

var outer = function () {
 var a = 1;

 var inner = function () {
  return ++a;
 };

 return inner; // return 을 사용함으로서  outer 함수를 종료시킴
};
var outer2 = outer();

console.log(outer2()); // 2
console.log(outer2()); // 3
outer = null; // 필요성이 없어지면 기본형 데이터를 할당해 참조 카운트를 0으로 만들어 메모리 누수를 막음

클로저 함수를 가장 잘 활용 할 수 있는 예시는 _addEventListener 가 있다. 또 다른 예시는 커링 함수가 있다. (고차함수)

var curry3 = function (func) {
 return function (a) {
  return function (b) {
   return func(a, b);
  };
 };
};

var getMaxWith10 = curry3(Math.max)(10);

console.log(getMaxWith10);

reference