文章出處


惰性載入函數

因為瀏覽器之間行為的差異,多數JavaScript代碼包含了大量的if語句,將執行引導到正確的代碼中,看看下面來自上一章的createXHR()函數。

        function createXHR(){
            if (typeof XMLHttpRequest != "undefined"){
                return new XMLHttpRequest();
            } else if (typeof ActiveXObject != "undefined"){
                if (typeof arguments.callee.activeXString != "string"){
                    var versions = ["MSXML2.XMLHttp.6.0", "MSXML2.XMLHttp.3.0",
                                    "MSXML2.XMLHttp"],
                        i, len;
            
                    for (i=0,len=versions.length; i < len; i++){
                        try {
                            new ActiveXObject(versions[i]);
                            arguments.callee.activeXString = versions[i];
                            break;
                        } catch (ex){
                            //skip
                        }
                    }
                }
            
                return new ActiveXObject(arguments.callee.activeXString);
            } else {
                throw new Error("No XHR object available.");
            }
        }

每次調用createXHR()的時候,它都要對瀏覽器所支持的能力仔細檢查。每次調用該函數都是這樣,即使每次調用時分支的結果不變:瀏覽器內置XHR,那么它就一直支持了,那么
這種測試就變得沒必要了。即使只有一個If語句的代碼,也肯定要比沒有If語句慢,所以如果If語句不必要每次執行,那么代碼可以運行地更快一些。解決方案就是稱之為惰性載入
的技巧。
惰性載入表示函數執行的分支僅會發生一次。有兩種實現惰性載入的方式。第一種就是在函數被調用時再處理函數,在第一次調用的過程中,該函數會被覆蓋為另外一個按合適方式
執行的函數,這樣第二次再調用的時候就不用再經過執行的分支了。

        function createXHR(){
            if (typeof XMLHttpRequest != "undefined"){
                createXHR = function(){
                    return new XMLHttpRequest();
                };
            } else if (typeof ActiveXObject != "undefined"){
                createXHR = function(){                    
                    if (typeof arguments.callee.activeXString != "string"){
                        var versions = ["MSXML2.XMLHttp.6.0", "MSXML2.XMLHttp.3.0",
                                        "MSXML2.XMLHttp"],
                            i, len;
                
                        for (i=0,len=versions.length; i < len; i++){
                            try {
                                new ActiveXObject(versions[i]);
                                arguments.callee.activeXString = versions[i];
                            } catch (ex){
                                //skip
                            }
                        }
                    }
                
                    return new ActiveXObject(arguments.callee.activeXString);
                };
            } else {
                createXHR = function(){
                    throw new Error("No XHR object available.");
                };
            }
            
            return createXHR();
        }
        
        var xhr1 = createXHR();
        var xhr2 = createXHR();

第二種實現惰性載入的方式是在聲明函數時就指定適當的函數。這樣,第一次調用函數時就不會損失性能了,而在代碼首次加載時會損失一點性能。

        var createXHR = (function(){
            if (typeof XMLHttpRequest != "undefined"){
                return function(){
                    return new XMLHttpRequest();
                };
            } else if (typeof ActiveXObject != "undefined"){
                return function(){                    
                    if (typeof arguments.callee.activeXString != "string"){
                        var versions = ["MSXML2.XMLHttp.6.0", "MSXML2.XMLHttp.3.0",
                                        "MSXML2.XMLHttp"],
                            i, len;
                
                        for (i=0,len=versions.length; i < len; i++){
                            try {
                                new ActiveXObject(versions[i]);
                                arguments.callee.activeXString = versions[i];
                                break;
                            } catch (ex){
                                //skip
                            }
                        }
                    }
                
                    return new ActiveXObject(arguments.callee.activeXString);
                };
            } else {
                return function(){
                    throw new Error("No XHR object available.");
                };
            }
        })();
        
        var xhr1 = createXHR();
        var xhr2 = createXHR();

重復的定時器

        setTimeout(function(){
        
           var div = document.getElementById("myDiv"),
               left = parseInt(div.style.left) + 5;
           div.style.left = left + "px";
        
           if (left < 200){
               setTimeout(arguments.callee, 50);
           }
        
        }, 50);

函數節流

函數節流背后的基本思想是指,某些代碼不可以在沒有間斷的情況下連續重復執行。第一次調用函數創建一個定時器,在指定的時間間隔之后運動代碼。當第二次調用該函數時,
它會清除前一次的定時器并設置另一個。如果前一個定時器已經執行過了,這個操作就沒有任何意義。然而,如果前一個定時器尚未執行,其實就是將其替換為一個新的定時器。
目的是只有在執行函數請求停止了一段時間 之后才執行。以下是該模式的基本形式:

 var processor={
   timeoutId:null,
    //實際進行處理的方法
   performProcessing:function(){
     //實際執行的代碼
   },
   process:function(){
    clearTimeout(this.timeoutId);
    
    var that=this;
    this.timeoutId=setTimeout(function(){
      that.performProcessing();
    },100
   }
 };

當調用了process(),第一步是清除存好的timeoutId,來阻止之前的調用被執行。然后,創建一個新定時器調用performProcessing()。由于setTimeout()中用到的函數環境總是
window,所以有必要保存this的引用以方便以后使用。
時間間隔設為了100ms,這表示最后一次調用process()之后至少100ms后才會調用performProcessing()。所以如果100ms之間內調用了process()共20次,performanceProcessing()
仍只會被調用一次。
這個模式可以用throttle()函數來簡化,這個函數可以自動進行定時器的設置和消除,如下例所示:

         function throttle(method, scope) {
            clearTimeout(method.tId);
            method.tId= setTimeout(function(){
                method.call(scope);
            }, 100);
        }
    
        function resizeDiv(){
            var div = document.getElementById("myDiv");
            div.style.height = div.offsetWidth + "px";
        }
        
        window.onresize = function(){
            throttle(resizeDiv);
        };

 


文章列表


不含病毒。www.avast.com
arrow
arrow
    全站熱搜
    創作者介紹
    創作者 大師兄 的頭像
    大師兄

    IT工程師數位筆記本

    大師兄 發表在 痞客邦 留言(0) 人氣()