所以我剛剛發現了這個有趣的記憶化小概念。
我已經開始閱讀有關它的文章,當我抓住這個想法的尾巴時就停止了。
然後我決定以我自己的方式並以我理解的方式找出簡單的解決方案。
如果您從未聽說過,記憶是儲存函數執行結果的過程,因此您可以在下次使用相同參數運行該函數時從一個小(或不那麼大)快取中提取它。
實際上,這對於高資源消耗的功能很有用。它伴隨著使用額外空間作為快取的成本。但它可以提高程式碼的速度以及使用它的用戶的體驗。
我玩了一下 JS 程式碼並提出了這個解決方案:
const memoize = fn => { const cache = {} return (...args) => { const fnKey = `${fn.name}(${args})`; if(!cache[fnKey]) { cache[fnKey] = fn(...args); } return cache[fnKey] }; }
然後你可以像這樣運行它:
function _add(x, y) { console.log("function runs", x, y); return x y; } const add = memoize(_add) add(42, 69) add(10, 15) add(10, 15)
這會導致函數執行兩次(#1 和 #2 'add' 呼叫)。第三個「新增」呼叫將使用緩存,因為它與#2 呼叫相同。
'function runs' 42 69 'function runs' 10 15
可以看到'function running' 10 15只被呼叫了一次。這是因為當我們第二次呼叫它時,快取正在被使用。
現在讓我們快速分解這裡發生的事情。
在這個例子中我們利用閉包機制來儲存快取。
const memoize = fn => { const cache = {} return () => { }; }
這允許我們拋出“fn”參數,這是最重要的,因為這正是我們想要操作的函數,向下作用域並“監聽”它的每個執行。
我確實是用最簡單、最天真的方式寫的。因此,我們將使用帶有參數的函數名稱作為快取的鍵,並將其執行結果作為值。
這意味著,執行:
add(2, 2)
結果為
// Our cache { 'add(2, 2)': 4 }
快取值。
我知道這可能不完全是「正確的方式」。但這個練習和這篇文章的想法並不是關於經過充分測試的安全和無邊緣情況的解決方案。
這是關於學習和簡單的實施。關於概念。所以我現在不關注實施細節。
現在,我們首先弄清楚函數呼叫的關鍵:
const memoize = fn => { const cache = {} return (...args) => { const fnKey = `${fn.name}(${args})`; }; }
我們將使用它來將函數執行的結果儲存在快取中。
然後我們檢查這個鍵(fnKey)是否已經存在。如果沒有,我們將鍵及其值設為傳遞的函數執行的結果。
最後我們總是從快取中傳回結果。因此,傳遞給 memoize 方法的函數的執行實際上總是以閉包結束(在「快取」物件中)。
我們現在只操作這個物件:
const memoize = fn => { const cache = {} return (...args) => { const fnKey = `${fn.name}(${args})`; if(!cache[fnKey]) { cache[fnKey] = fn(...args); } return cache[fnKey] }; }
就是這樣。
現在我要去看看應該如何「正確」地完成它。但如果您覺得這很有趣,請告訴我。如果這種方法有任何不清楚或錯誤的地方(根據您的口味),請刪除評論,讓我們討論一下。
謝謝,再見!
免責聲明: 提供的所有資源部分來自互聯網,如果有侵犯您的版權或其他權益,請說明詳細緣由並提供版權或權益證明然後發到郵箱:[email protected] 我們會在第一時間內為您處理。
Copyright© 2022 湘ICP备2022001581号-3