如果你閱讀過一些常用的js庫源碼,可能對很多高級的寫法就有所瞭解,本篇博文筆者將之前閱讀源碼中遇到的相關關於函數的牛逼寫法做一總結,最主要是對緩存函數 memozition、函數柯里化Currying、偏函數partial application的詳解。
緩存函數 memozition
1.1概念
緩存函數指,函數將上次計算結果緩存起來,當下次調用函數時如果遇到相同的參數則直接將緩存結果返回,節省運算時間,當然犧牲了存儲空間。
1.2實現原理
把參數和運算結果存儲到一個對象中,函數調用時判斷該參數下對應的數據是否存在,存在則返回結果,否則開始計算返回結果,並存儲參數和結果。
緩存:閉包;
運算方法:高階函數;
實現
經典應用 斐波那契函數
求斐波那契數列第n項數據值:
不用緩存:
let v = 0;
let fibonacci = function(n){
v++;
if(n<2){
return 1;
}else{
return fibonacci(n-1)+fibonacci(n-2);
}
}
// 打印前10項
for(let i=0;i<11;i++){
console.log(fibonacci(i));
}
console.log("函數執行了:"+v+"次")
結果:我們看到遞歸函數運行了453次
用緩存函數優化:
let v = 0;
let fibonacci = function(n){
v++;
if(n<2){
return 1;
}else{
return fibonacci(n-1)+fibonacci(n-2);
}
}
//簡單緩存函數
const memorize = function(fn) {
const cache = {} // 存儲緩存數據的對象
return function(...args) { // 這裏用到數組的擴展運算符
const _args = JSON.stringify(args) // 將參數作爲cache的key
return cache[_args] || (cache[_args] = fn.apply(fn, args)) // 如果已經緩存過,直接取值。否則重新計算並且緩存
}
}
fibonacci = memorize(fibonacci)
for(let i=0;i<11;i++){
console.log(fibonacci(i));
}
console.log("函數執行了:"+v+"次")
結果:
結果被優化僅僅執行了11次;
緩存函數優化:
let memoize = function(fn,hash){
let me = function(key){
let cache = me.cache;
let address = ""+(hash?hash.apply(this,arguments):key);
if(! cache[address]){
cache[address] = fn.apply(this,arguments);
}
return cache[address];
}
me.cache = {};
return me;
}
fibonacci = memoize(fibonacci)
for(let i=0;i<11;i++){
console.log(fibonacci(i));
}
console.log("函數執行了:"+v+"次")
通過以上結果分析,用了緩存函數之後運算次數從453次減少到11次,如果我們打印前100次,如果不用緩存函數瀏覽器必然卡死,而用了緩存函數則就是幾毫秒的事。