0

David Flanagan의 "Javascript : The Definitive Guide"를 살펴 보겠습니다.Flanagan의 "JS : Definitive Guide"에 memoize 기능이 필요한 이유는 무엇입니까? length?

그가 인수로 함수를 받아들이는 고차 기능, memoize()을 보여주고 기능의 memoized 버전 반환 단락 8.8.4에서

:이 설명에서

//Return a memoized version of f. 
// It only works if arguments to f all have distinct string representations. 
function memoize(f) { 
     var cache = {}; // Value cache stored in the closure. 

     return function() { 
      // Create a string version of the arguments to use as a cache key. 
      var key = arguments.length + Array.prototype.join.call(arguments,","); 
      if (key in cache) return cache[key]; 
      else return cache[key] = f.apply(this, arguments); 
     } 
} 

은 "반환 함수 은 인수 배열을 문자열 "으로 변환합니다.

인수 만 필요하면 왜 인수 배열을 문자열로 변환하는 대신 arguments.lengthArray.prototype.join.call(arguments, ",")과 연결해야합니까? 그렇지 않으면이 두 호출이 동일한 키에 저장 될 수 있기 때문에

+0

나중에 호출 캐시에 액세스하기 때문에 사용됩니다. 다른 수의 매개 변수를 사용하여 메서드를 호출하면 차이가 있습니다. –

답변

4

는 : 같은 문자열로 인수 결과에 합류 두 경우 모두

memoizedFunc('', ''); 
memoizedFunc(','); 

: ,

1

이 기능은 끊어집니다. 모든 인수가 문자열 일 때도 작동하지 않습니다. 이 예를 참조하십시오

//Return a memoized version of f. 
 
// It only works if arguments to f all have distinct string representations. 
 
function memoize(f) { 
 
     var cache = {}; // Value cache stored in the closure. 
 

 
     return function() { 
 
      // Create a string version of the arguments to use as a cache key. 
 
      var key = arguments.length + Array.prototype.join.call(arguments,","); 
 
      if (key in cache) return cache[key]; 
 
      else return cache[key] = f.apply(this, arguments); 
 
     } 
 
} 
 

 
const f = memoize(function(...args) { 
 
    console.log('f was called') 
 
    return args 
 
}) 
 

 
console.log(f(',', '')) 
 
console.log(f('', ','))

가 반환해서는 안 함수가 다른 인수로 호출되는 두 번째는 캐시 된 값을 반환합니다. 그러나 'f was called'은 한 번만 기록되므로 예상대로 작동하지 않습니다.


모든 경우에 작동 할 함수를 만들려면 캐시에 모든 인수를 저장해야하고, 그들이 같은 경우 확인을 반복하는 것입니다. 그런 식으로 구현 될 수있다 :

const memoize = function(f) { 
 
    const cache = [] 
 
    return (...args) => { 
 
    for (const element of cache) { 
 
     let hasSameArguments = true 
 
     for (const i of args.keys()) { 
 
     if (args[i] !== element.args[i]) { 
 
      hasSameArguments = false 
 
      break 
 
     } 
 
     } 
 
     if (hasSameArguments) { 
 
     return element.value 
 
     } 
 
    } 
 
    const value = f(...args) 
 
    cache.push({value, args}) 
 
    return value 
 
    } 
 
} 
 

 
const f = memoize(function(...args) { 
 
    console.log('f was called') 
 
    return args 
 
}) 
 

 
console.log(f(',', '')) 
 
console.log(f('', ',')) // different arguments, f is called again 
 

 
console.log(f(true)) 
 
console.log(f(true)) // from cache 
 

 
const someObj = {} 
 
    ,otherObj = {} 
 

 
console.log(f(someObj)) 
 
console.log(f(someObj)) // the same object, result from cache 
 
console.log(f(otherObj)) // different object, f is called again 
 
console.log(f(otherObj)) 
 

 
console.log(f([1, 2, 3])) 
 
console.log(f([1, 2, 3])) // different object, f is called again 
 
          // (because [1, 2, 3] !== [1, 2, 3])
는 예를 들어 동일한 값을 포함하는 배열을 두 번 함수를 호출하는 경우, 그래서 === 연산자를 사용하여 인수를 비교하는 것이

주, 그것은 반환하지 것입니다 캐쉬 된 결과. 인수를 반복적으로 반복하고 모든 속성이 같은지 확인하여이 동작을 변경할 수 있습니다.

+1

또는 Map()을 사용하여 복잡한 값을 키로 저장할 수 있습니다. https://github.com/thinkloop/memoizerific – Baz