實作 javascript cache function
TWGD / 2019-01-11
題目
假設現在有一個 function 叫做 complexCalculation,裡面跑了很複雜的數學運算所以要跑很久,例如說:
console.log(complextCalculation(10)) // 印出 123,跑了 5 秒
console.log(complextCalculation(10)) // 印出 123,跑了 5 秒
可是對這種運算來說,只要傳進去的參數一樣,結果就一樣,所以我可以把結果給快取起來,再跑一次 function 的時候就不用重新做這些複雜的運算,所以理想的情形下是這樣:
var cachedComplextFunc = cached(complextCalculation)
console.log(cachedComplextFunc(10)) // 印出 123,跑了 5 秒
console.log(cachedComplextFunc(10)) // 立刻印出 123
現在請你實作出 cached
這個 function,讓上面的程式碼可以順利運行
var cachedComplextFunc = cached(complextCalculation)
console.log(cachedComplextFunc(10)) // 印出 123,跑了 5 秒
console.log(cachedComplextFunc(10)) // 立刻印出 123
解題心得:
要做到 cache 住運算結果,要運用 closure 閉包的概念。
function cached(){}
裡面有一個 object ( cache = {}
) 用來記住之前的結果,然後 return 另一個 function 出去。
用變數 cachedComplextFunc 來接這個 return 出來的 function。
之所以可以記住變數,是因為底層 scope chain 的關係,function cached(){}
裡面的 cache 這個 object 會被 keep 住。
一、當只有一個參數的時候:(參數是數字)
const cached = (func) => {
let cache = {};
return (key) => {
if(key in cache){
return cache[key];
} else {
let ans = func(key);
cache[key] = ans;
return ans;
}
}
}
就是把傳進來的參數當作 cache 這個 object 的 key,運算結果當作 value 給保存起來。 之後 cachedComplextFunc 有參數傳進來,若 object 有這個參數的 key,就回傳之前運算過保留的結果。 若沒有的話,就執行運算 function,然後存進 object。
二、當有多個參數的時候:(參數都是數字)
const cached = (func) => {
let cache = {};
return (...key) => {
if(key in cache){
return cache[key];
} else {
let ans = func(...key);
cache[key] = ans;
return ans;
}
}
}
概念跟前面一樣,只是會碰到『要怎麼把多個參數傳進去?』的問題。
ES6 可以用 rest operator ...
,傳進來的參數會轉成一個 array。
另外,存進去 object 的方式也是一樣把所有傳進來的參數當作 key。
三、當參數型態除了數字也可能是字串、陣列、物件:
const cached = (func) => {
let cache = {};
return (...args) => {
let key = JSON.stringify(args);
if(key in cache){
console.log('cached')
return cache[key];
}
let ans = func(...args);
cache[key] = ans;
return ans;
}
}
這邊會遇到 object 型態的參數無法儲存為 key 的問題。
所有 object 只會顯示 [object object]。
因此需要用 JSON.stringify()
轉換成 JSON 字串儲存。
其他問題:字串化後,object key 的順序,造成判定成不同 object 的問題。(未完)
重點概念整理:
obj[]
存取到。Array.from(arguments)
或 ...
(rest parameter) 來把參數 ( array-like ) 轉換成 array。
P.S. Arrow function 沒有自己的 arguments
物件。JSON.stringify()
轉換成 JSON 字串,才可以儲存。(JSON.stringify()
不能處理 function )