簡體   English   中英

為什么D. Flanagan的“ JS:權威指南”中的記憶功能需要arguments.length?

[英]Why does memoize function in D. Flanagan's “JS: Definitive Guide” need arguments.length?

我正在閱讀David Flanagan的“ Javascript:權威指南”。

在8.8.4段中,他顯示了一個高階函數memoize() ,該函數接受一個函數作為其參數並返回該函數的記憶版本:

 //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數組轉換為字符串 ”。

如果我們只需要爭論,為什么他串聯arguments.lengthArray.prototype.join.call(arguments, ",")而不是只轉換參數數組為字符串?

因為否則這兩個調用將使用相同的密鑰存儲:

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

在兩種情況下,連接參數的結果都使用相同的字符串: ,

此功能已損壞。 即使所有參數都是字符串,它也不起作用。 請參閱以下示例:

  //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]) 

請注意,它使用===運算符比較參數,因此,例如,如果使用包含相同值的數組兩次調用該函數,則不會返回緩存的結果。 您可以通過深度迭代參數並檢查所有屬性是否相同來更改此行為。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM