0

私はDavid Flanaganの「Javascript:The Definitive Guide」を見ています。D. Flanaganの "JS:Definitive Guide"にmemoize関数が引数を必要とするのはなぜですか?length?

彼はその引数としての機能を受け入れ、高階関数、 memoize()を示しており、機能のメモ化バージョンを返しパラグラフ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

関連する問題