Closure

난 Closure를 사용하지 않는다. 하지만 이에 대해 질문을 너무 받아서 공부하여 정리한다.
Closure는 함수안에서 함수를 호출하는 것이며 이때 변수 scope을 유지하는, 즉 실행 컨텍스트를 유지될때 를 말한다. 즉 함수와 scope을 같이 들고 다닌다고 생각하면 된다.
더 풀어쓰면 함수 A안에 함수 B를 선언하여 리턴할때 B가 A내의 scope(변수, 함수 값)를 기억하게 되어 함수 A밖에서도 해당 scope의 값을 사용할 수 있는 것이다.

다음과 같은 코드가 바로 Closure 이다.

function A(cnt) {
  let undici = 11;
  function B() {
    return  undici + cnt;
  }
  return B;
}

const d1 = A(10);
console.log('aaaa', d1());
const d2 = A(20);
console.log('aaaa', d2());

d1, d2는 B함수이다. 그리고 클로저를 이용함에 따라 A함수 밖으로나와서도 undici 변수를 기억하여 사용할 수 있다.

아니면 아래와 같이 토글 상태를 기억하게 할 수도 있다.

function to(cnt) {
  let toggle = true;

  function ggle() {
    toggle = !toggle;
    return  !toggle;
  }
  return ggle;
}

const d1 = to();
console.log('aaaa', d1());
console.log('aaaa', d1());

참고로 함수 실행이 아닌 선언 시점에 변수의 범위가 결정되는 것을 lexical scope이라고 한다. 자바스크립트는 lexical scope이며 const, var는 함수 단위의 scope을 갖고, let은 block 단위의 scope을 갖는다.
closure를 이용하여 이 lexical scope을 기억하게 하면 함수밖에서도 scope을 유지시킬수 있다.

Typescript private variable

아래와 같은 Animal 클래스가 있고 name이 private 변수로 선언되어있다고 하자.

class Animal {
  private name: string;

  getName() {
      return this.name;
  }

  setName(ss) {
      this.name = ss;
  }
}

const aa = new Animal();

이 typescript는 javascript로 다음과 같이 트랜스파일된다.

var Animal = /** @class */ (function () {
    function Animal() {
    }
    Animal.prototype.getName = function () {
        return this.name;
    };
    Animal.prototype.setName = function (ss) {
        this.name = ss;
    };
    return Animal;
}());
var aa = new Animal();

console.log('11111', aa.getName());
console.log('22222', aa.setName('hihi'));
console.log('33333', aa.getName());

private 변수를 만들어주기위해 clousre를 사용했다.

주의점

마지막으로 Closure 사용시 주의할 점은 Closure를 다사용하고 난 이후에는 명시적으로 null 등을 assign해주어야 한다. 그렇지 않으면 GC 대상이 되지 않으므로 메모리 부족을 유발시킬 수 있다.

References

  • https://developer.mozilla.org/ko/docs/Web/JavaScript/Closures
  • https://poiemaweb.com/js-closure

realjays

반박시 당신말이 맞습니다.