這篇文章主要介紹了JavaScript學習筆記之函數記憶,小編覺得挺不錯的,現在分享給大家,也給大家做個參考。一起跟著小編過來看看吧
本文講解函數記憶與菲波那切數列的實現,分享給大家,具體如下
##定義
function add(a, b) { return a + b; } // 假设 memorize 可以实现函数记忆 var memoizedAdd = memorize(add); memoizedAdd(1, 2) // 3 memoizedAdd(1, 2) // 相同的参数,第二次调用时,从缓存中取出数据,而非重新计算一次
#原則
第一版
// 第一版 (来自《JavaScript权威指南》) function memoize(f) { var cache = {}; return function(){ var key = arguments.length + Array.prototype.join.call(arguments, ","); if (key in cache) { return cache[key] } else return cache[key] = f.apply(this, arguments) } }
var add = function(a, b, c) { return a + b + c } var memoizedAdd = memorize(add) console.time('use memorize') for(var i = 0; i < 100000; i++) { memoizedAdd(1, 2, 3) } console.timeEnd('use memorize') console.time('not use memorize') for(var i = 0; i < 100000; i++) { add(1, 2, 3) } console.timeEnd('not use memorize')
注意
第二版
var propValue = function(obj){ return obj.value } var memoizedAdd = memorize(propValue) console.log(memoizedAdd({value: 1})) // 1 console.log(memoizedAdd({value: 2})) // 1
// 第二版 (来自 underscore 的实现) var memorize = function(func, hasher) { var memoize = function(key) { var cache = memoize.cache; var address = '' + (hasher ? hasher.apply(this, arguments) : key); if (!cache[address]) { cache[address] = func.apply(this, arguments); } return cache[address]; }; memoize.cache = {}; return memoize; };
var add = function(a, b, c) { return a + b + c } var memoizedAdd = memorize(add) memoizedAdd(1, 2, 3) // 6 memoizedAdd(1, 2, 4) // 6
var memoizedAdd = memorize(add, function(){ var args = Array.prototype.slice.call(arguments) return JSON.stringify(args) }) console.log(memoizedAdd(1, 2, 3)) // 6 console.log(memoizedAdd(1, 2, 4)) // 7
適用場景
var count = 0; var fibonacci = function(n){ count++; return n < 2? n : fibonacci(n-1) + fibonacci(n-2); }; for (var i = 0; i <= 10; i++){ fibonacci(i) } console.log(count) // 453
所以執行的總次數為:177 + 109 + 67 + 41 + 25 + 15 + 9 + 5 + 3 + 1 + 1 = 453 次!
如果我們使用函數記憶呢?
var count = 0; var fibonacci = function(n) { count++; return n < 2 ? n : fibonacci(n - 1) + fibonacci(n - 2); }; fibonacci = memorize(fibonacci) for (var i = 0; i <= 10; i++) { fibonacci(i) } console.log(count) // 12
所以我們還需要認真看下我們的寫法,在我們的寫法中,其實我們用生成的fibonacci 函數覆蓋了原本了fibonacci 函數,當我們執行fibonacci(0) 時,執行一次函數,cache 為{ 0: 0},但是當我們執行fibonacci(2) 的時候,執行fibonacci(1) + fibonacci(0),因為fibonacci(0) 的值為0, !cache[address]
的結果為true,又會執行一次fibonacci 函數。原來,多出來的那一次是在這裡!
多說一句
也許你會覺得在日常開發中又用不到fibonacci,這個例子感覺實用價值不高吶,其實,這個例子是用來表示一種使用的場景,也就是如果需要大量重複的計算,或者大量計算又依賴先前的結果,便可以考慮使用函數記憶。而這種場景,當你遇到的時候,你就會知道的。
以上是JavaScript有關函數的介紹的詳細內容。更多資訊請關注PHP中文網其他相關文章!