JavaScript高級プログラム設計学習ノート--高級技術

13065 ワード

不活性ロード関数
ブラウザ間の挙動の違いのため、多くの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);
関数の流れ
関数の流れの背後にある基本的な考え方とは、いくつかのコードが途切れることなく連続して実行されてはならないことを意味します.最初の呼び出し関数は、指定された時間間隔の後に動作コードを作成します.この関数を2回目に呼び出すと、前回のタイマーをクリアして他の設定を行います.前のタイマーがすでに実行されていたら、この操作は何の意味もありません.しかし、前のタイマーがまだ実行されていない場合、新しいタイマーに置き換えられます.目的は、実行関数要求が一時停止された後にのみ実行されます.以下はこのモードの基本形式です.
 var processor={
   timeoutId:null,
    //         
   performProcessing:function(){
     //       
   },
   process:function(){
    clearTimeout(this.timeoutId);
    
    var that=this;
    this.timeoutId=setTimeout(function(){
      that.performProcessing();
    },100
   }
 };
プロcessを呼び出すと、最初のステップは、保存済みのtimeoutIdをクリアして、前の呼び出しを停止します.その後、新しいタイマーを作成して、performProcessingを呼び出します.setTimeout()で使用される関数環境は常にwindowであるため、今後の使用を容易にするためにthisの引用を保存する必要があります.時間間隔は100 msに設定されています.これは最後にプロシーズを呼び出した後、少なくとも100 ms後に、performProcessingを起動するという意味です.したがって、100 msの間にプロシーズを20回呼び出したら、performancProcessingはまだ一回だけ呼び出されます.このモードは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);
        };