JavaScriptブラウザを越えたイベント関数の最適化

5068 ワード

JavaScriptは、イベントに基づいて駆動される言語(特にDOMで動作する場合)として、常にDOMのためにさまざまなイベントを結びつける必要があります.しかしながら、低いバージョンのIEの不給力のために、バインディングイベントと削除イベントの傍受においては異なるものがあり、我々はしばしば、ブラウザを介したバインディング(除去)イベントの関数を自分でカプセル化する必要がある.ブラウザを介してDOMイベントを追加(削除)する非常に古典的な実装コードは以下の通りです.
//        
function addHandler(target, eventType, handler) {
  if(target.addEventListener) { //DOM2 events
    target.addEventListener(eventType, handler, false);
  } else { //IE
    target.attachEvent("on" + eventType, handler);
  }
}
 
//        
function removeHanler(target, eventType, handler) {
  if(target.removeEventListener) { //DOM2 events
    target.removeEventListener(eventType, handler, false);
  } else { //IE
    target.detachEvent("on", eventType, handler);
  }
}
    上記のコードの実現の考え方は、まず、ブラウザがDOM 2のイベントをサポートしているかどうかを判断し、サポートしているなら、addEventListenerでイベントを追加し、removeveveventListenerでイベントを削除することです.サポートされていない場合は、デフォルトは下位バージョンのieブラウザであり、ie特有の方法を使用する.
    一見、上のコードは十分に最適化されているようです.隠し性能の問題は
関数が呼出されるたびに、繰り返し作業を行います.ブラウザの種類を検出します.これは消耗性能を比較して、特に大量のイベントを結びつけて、繰り返し起動する時です.実は、これは必要ではないです.一回だけ判断すればいいです.ページのロードが完了すると、ブラウザのタイプが確定していますので、今はIEです.そしてブラウズしているうちに、突然chromeになります.したがって、上のコードを最適化して、ブラウザを一度だけ測定する必要があります.一度だけの測定を可能にする二つの方法がありますが、それぞれの方法を検討してみます.
  一つ目は、最初にイベント関数の追加(削除)を呼び出すと、どの方法でイベントをバインディングまたは削除するかを検出し、決定し、関数を書き換え、正しい動作を含む新しい関数で古い関数を上書きします.
そして古い関数の最後にこの新しい関数を呼び出します.上のコードを書き換えたら次のようになります.
//    
function addHandler(target, eventType, handler) {
 
  //       ,    addHanler  
  if(target.addEventListener) { //DOM2
    addHandler = function(target, eventType, handler) {
      target.addEventListener(eventType, handler, false);
    };
  } else { //IE
    addHandler = function(target, eventType, handler) {
      target.attachEvent("on" + eventType, handler);
    };
  }
   
  //      
  addHandler(target, eventType, handler);
}
 
//    removeHanler
function removeHandler(target, eventType, handler) {
 
  //       ,    removeHandler  
  if(target.removeEventListener) { //DOM2
    removeHandler = function(target, eventType, handler) {
      target.removeEventListener(eventType, handler, false);
    };
  } else { //IE
    removeHandler = function(target, eventType, handler) {
      target.detachEvent("on" + eventType, handler);
    };
  }
 
  //      
  removeHandler(target, eventType, handler);
}
    注意したいのは、2つの関数の最後の行で、書き換えられた新しい関数、例えばaddHandlerを呼び出しました.removeHandlerと;これは必要です.新しい関数で古い関数をカバーしています.古い関数で新しい関数を呼び出して初めて実行します.
    もう一つの最適化方法は、ブラウザのタイプを事前に検出し、正しい操作関数を変数に割り当てます.私たちは三つの条件演算子を使って実現できます.コードは以下の通りです.
//    
var addHandler = document.body.addEventListener ?
          function(target, eventType, handler) { //DOM2
            target.addEventListener(eventType, handler,false);
          } :
          function(target, eventType, handler) { //IE
            target.attachEvent("on" + eventType, handler);
          };
// var removeHandler = document.body.removeEventListener ?             function(target, eventType, handler) { //DOM2               target.removeEventListener(eventType, handler, false);             } :             function(target, eventType, handler) { //IE               target.detachEvent("on" + eventType, handler);             }
    この方法は前のようなより積極的で、関数の呼び出し前からブラウザのタイプを検出していますので、呼び出し時にはすぐにイベントをバインドすることができます.
PS:
参考資料:
Nicbolas C.Zakas《High Performance JavaScript》;chapter 8;Don’t Repeat Work
この本は英語版だけで、中国語版はまだないようです.必要なものがあればGoogleでダウンロードしてみてください.