![](/img/trans.png)
[英]What is the difference between function.length and arguments.length in JS
[英]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.length
與Array.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.