介紹JavaScript中Memoization的技巧
Memoization是一種讓你的應用程式大大加速的技巧。
儘管我將這篇文章標記為“JavaScript”,但Memoization並不是JavaScript獨有的技術,我會提供一些JavaScript的例子。
Memoization是在我們運行函數後,將函數調用的結果存儲在該函數本身中的動作。下次調用該函數時,它不會再次執行“常規”運算,而是直接返回存儲的結果。
這其實是對函數進行緩存。
為什麼這很有用?
假設我們的函數需要1秒的執行時間,而Memoization可以將這個過程加速到2毫秒。這裏明顯有個好處。
聽起來很酷。有什麼限制嗎?
Memoization僅在調用帶有相同參數集的函數時,結果相同的情況下才有效。換句話說,函數必須是純函數。否則,對結果進行緩存就沒有意義。
因此,無法優化使用Memoization的操作包括數據庫查詢、網絡請求、文件讀寫等非純函數操作。對於這些情況,您將需要找到其他方法來進行優化。或者接受它們的低效率,有時是不可避免的。
讓我們創建一個例子:
// 計算num的階乘
const fact = num => {
if (!fact.cache) {
fact.cache = {}
}
if (fact.cache[num] !== undefined) {
console.log(num + ' cached')
return fact.cache[num];
} else {
console.log(num + ' not cached')
}
fact.cache[num] = num === 0 ? 1 : num * fact(num - 1)
return fact.cache[num]
}
這個例子計算一個數字的階乘。當第一次運行fact()
時,它在函數本身上創建一個cache
物件屬性,用於存儲計算的結果。
每次調用時,如果在cache
物件中找不到數字的結果,我們進行計算。否則,我們只返回那個結果。
試著運行它。我製作了一個Codepen來方便測試,它使用document.write()
來輸出到HTML頁面(這是我很久以前用document.write()
,但這次它很有用)。
請參考Memoization Example Factorial的Codepen鏈接查看運行結果。
有一些庫可以為任何純函數添加Memoization功能,這樣您就可以跳過修改函數本身的任務,只需使用這個功能將其裝飾起來。
特別要提到的是fast-memoize。
如果您是Lodash的粉絲,Lodash還有一個memoize()
方法。