javascript函數記憶

在js代碼層次上緩存函數執行結果

在編寫代碼時,會有函數屢次重複調用
到的也有多是相同的結果
那麼能夠把函數執行的結果緩存起來,下次調用時,直接從緩存中獲取
函數就不會重複執行,從而達到優化代碼的執行速度。緩存

什麼是記憶

在計算中,記憶是一種優化技術,主要用於經過存儲昂貴的函數調用的結果並在次出現相同的輸入時返回緩存的結果來加速計算機程序

具體的實現思路

記憶的定義基本上描述了實施該技術的有用方案。
當您擁有一個昂貴的函數時,若是給定相同的參數,該函數將始終致使相同的值,則緩存結果並在下次調用它時返回緩存的值很是有效。
這樣,寶貴的時間不會浪費在從新計算值上

簡單的實現

;(function(root){    // root 是一個對象
        // 把參數hash成32-bit數字
        // 拓展Stirng構造函數的原型對象
        
        String.prototype.checksum = function(){
            var checksum = 0 , i , chr , len;
            //判斷調用checksun函數的字符串的長度
            if(this.length == 0){
                return checksum;
            }
            
            // 循環 hash參數字符串
            // <<  |  位運算
            for( i = 0 , len = this.length ; i++){
                checksum = ((((checksum << 5) - checksum) + this.charCodeAt(i)) | 0);
            }
            // 返回hash 的值
            return checksum;
        }
            
        // 建立一個函數 參數是要優化的函數
        var memoize = function(f){
            // 判斷參數是否是函數 
            if(typeof f !== 'function' || !(f instanceof Function){
                throw new TypeError('參數不是一個函數')
            }
            
            // 建立一個緩存結果對象
            var cache = {};
            
            // 調用memoize函數,最終會返回這個函數
            return function(){
                var checksum = 0;
                // 判斷參數 若是參數大於0
                if(arguments.length > 0){
                    // 把參數hash
                    checksum = JSON.stringify(arguments).checksum();
                }
                
                // 判斷參數hash的結果是否在 緩存對象 cache 中
                // 不在,則把函數執行的結果存儲到cache對象上,k是參數的hash結果
                if(typeof cache[checksum] === 'undefined'){
                    // 經過apply把參數都傳入到調用的函數中
                    cache[checksum] = f.apply(f, arguments);
                }
                // 把結果返回
                return cache[checksum];
            }
        }
        // 把函數掛在在root的memoize屬性上
        root.memoize = memoize;
   // 判斷window中是否有men屬性,若是有,則傳入men屬性,若是沒有,則定義window.men是一個對象
   })('men' in window ? window.men : window.men = {});

示例

// 斐波那契數列
    var fib = function(n){
        if(n === 1) return 1;
        if(n === 2) retrun 2;
        return fib(n - 1) + fib(n - 2);
    }
   
    // 直接屢次調用函數
    console.time();
    fib(20);
    console.timeEnd();  //1ms多
    
    console.time();
    fib(20);
    console.timeEnd():  // 0.8 0.9ms多
        
     // 使用封裝好的函數,去優化fib函數。返回值是優化好的函數
    var result = men.memoize(fib);
    
    console.time();
    result(30);
    console.timeEnd();  // 8.54296875ms
    
    console.time();
    result(30);
    console.timeEnd();  // 0.014892578125ms
相關文章
相關標籤/搜索