2016년 11월 4일 금요일

[javascript patterns][메모이제이션(Memoization) 패턴] 스터디 12


함수프로퍼티 - 메모이제이션(Memoization)패턴

함수는 객체이기 때문에 프로퍼티를 가질 수 있다. 사실 함수는 생성될 때부터 프로퍼티와 메서드를 가지고 있다. 그 예가 length다. length는 함수가 받는 인자의 개수를 값으로 가진다.
function func(a, b, c) {}
console.log(func.length); // 3
언제들지 함수에 사용자 정의 프로퍼티를 추가할 수 있다. 함수에 프로퍼티를 추가하여 결과(반환 값)을 캐시하면 다음 호출 시섲ㅁ에 복잡한 연산을 반복하지 않을 수 있다. 이런 방법을 메모이제이션 패턴이라고 한다.
var myFunc = function(param) {
  if (!myFunc.cache[param]) {
    var result = {};
    //... 비용이 많이 드는 수행 ...
    myFunc.cache[param] = result;
  }
  return myFunc.cache[param];
};

//캐시 저장공간
cache 프로퍼티는 함수로 전달된 param 매개변수를 키로 사용하고 계산의 결과를 값으로 가지는 객체(해시)다. 위 코드의 문제는 myFunc함수가 단 하나의 매개변수를 받는다고 가정하고 있다. 게다가 이 매개변수는 문자열과 같은 원시 데이터 타입이라고 가정한다.
더 많은 매개변수와 복잡한 타입을 갖는다면 어떻게 해야 할까? (직렬화하여 해결한다.)
var myFunc = function() {
  var cachekey = JSON.stringify( Array.prototype.slice.call(arguments)),
      result;

  if (!myunc.cache[cachekey]) {
    result = {};
    //비용이 많이 드는 수행...
    myFunc.cache[cachekey] = result;
  }
};

// 캐시 저장공간
myFunc.cache = {};
직렬화하면 객체를 식별할 수 없게 되는 것을 주의하라. 만약 같은 프로퍼티를 가지는 두 개의 다른 객체를 직렬화하면, 이 두 객체는 같은 캐시 항목을 공유하게 될 것이다.
이 함수를 작성하는 다른 방법으로는 하드코딩 대신 arguments.callee를 사용해 함수를 참조할 수 있다. (하지만 곧 사라질 운명이다. 쓰지 않는 것이 낫다. 명심)
var myFunc = function (param) {
  var f = arguments.callee,
      result;

  if (!f.cache[param]) {
    result = {};
    //...비용이 많이 드는 수행...
    f.cache[param] = result;
  }
  return f.cache[param];
};

// 캐시 저장공간
myFunc.cache = {};
};

댓글 없음:

댓글 쓰기