JavaScriptクライアント検出--「コンピテンシー検出」の注意点

3516 ワード

クライアント検出
やむを得ない場合は、クライアント検出を使用しないでください.より汎用的な方法が見つかれば,より汎用的な方法を優先的に採用すべきである.最も一般的なシナリオを設計してから、ブラウザ固有のテクノロジーを使用してシナリオを強化します.
コンピテンシーテスト
きほんモードこうぶん
ターゲットは特定のブラウザを識別するのではなく、ブラウザを識別する能力です.基本モードは次のとおりです.
if (object.propertyInQuestion){
    //  object.propertyInQuestion
}
例えば、IE 5.0以前のバージョンではdocument.getElementById()というDOMメソッドはサポートされていません.ただしdocument.all[]メソッドは使用できます.次のコードを書くことができます.
function getElement(id){
    if (document.getElementById){
        return document.getElementById(id);
    }else if (document.getAll){
        return document.getAll[id];
    }else{
        throw new Erroor("No way to retrieve element !");
    }
}
コンピテンシーチェック使用のポイント
  • まず目的を達成する最もよく使われる特性を検出し、コードの最適化を保証し、複数の条件を検出することを避けることができる.
  • は、実際に使用される特性をテストしなければならない.

  • 2番目のポイント:
    function getWindowWidth(){
        if (document.all){ //    IE    
            return document.documentElement.clientWidth; //  !     IE    
        } else {
            return window.innerWidth;
        }
    }
    
    Operaがdocument.allをサポートし、window.innerWidthもサポートします.上記のコードの使い方に問題があります.
    より信頼性の高いコンピテンシー検出
    能力検出は、ある特性が適切な方法で行動するかどうかを知るのに役立ちます.オブジェクトがソートをサポートしているかどうかを検出するには、次の手順に従います.
    function isSortable(obj){
        return typeof obj.sort == "function";
    }
    
    var obj1 = [321,43215,1];
    var obj2 = {
        name: "Oliver",
        age: 18
    };
    
    console.log(isSortable(obj1)); //true
    console.log(isSortable(obj2)); /false
    
    ここで注意しなければならないのは、能力検出は対応する方法だけが存在するかどうかを検出することではありません!!!
    function isSortable(obj){
        return !!obj.sort;
    }
    
    var obj1 = [321,43215,1];
    var obj2 = {
        name: "Oliver",
        age: 18,
        sort: true
    };
    
    console.log(isSortable(obj1)); //true
    console.log(isSortable(obj2)); //true
    
    ここで問題点は,能力検出は対応する方法が存在するか否かを検出するものではなく,obj 2にsort属性が定義されており,いわゆる能力検出によりtrueとして検出できることである.
    したがって、可能な場合は、できるだけtypeofを使用して能力検査を行う必要があります.
    IEでは、状況が異なります.
    function hasCreateElement(){
        return typeof document.createElement == "function";
    }
    
    IE 8の前に、この関数はfalseを返します.typeof document.createElementは「function」ではなく「object」を返します.IEおよびそれ以前のバージョンのホストオブジェクトはJscriptではなくCOMによって実現されるからである.しかし,IE 9ではこの問題を修正し,すべてのDOMメソッドに対して「function」を返す.
    コンピテンシー検出、ブラウザ検出ではありません
    実際の開発では,ユーザがどのブラウザを使用しているかを判断するのではなく,能力検出を次のソリューションを決定する根拠とすべきである.例えば:
    var hasNSPlugins = !!(navigator.plugins && navigator.plugins.length);
    var hasDOM1 = !!(document.getElementById && document.getElementsByTagName && document.createElement);
    
    上記のコードの1つは、ブラウザがNetscapteスタイルをサポートしているかどうかを判断するためのプラグインです.もう1つは、ブラウザがDOM 1レベルで規定された能力を備えているかどうかを判断するためのものである.
    変な癖の検査
    ターゲットはブラウザの特殊な動作を識別することです.変な癖の検出はブラウザにどんな欠陥があるかを知りたいことです.例えば、IE 8以降のバージョンにバグが存在する.すなわち、インスタンス属性がfalseとマークされたプロトタイプ属性と同名である場合、そのインスタンスはfor-inループに現れない.このような「変な癖」を検出するには、次のコードを使用します.
    var hasDontEnumQuirk = function(){
        var o = { toString : function(){} };
        for (var prop in o){
            if (prop == "toString"){
                return false;
            }
        }
        return true;
    }();
    
    また、Safari 3以前のバージョンでは隠された属性が列挙されていた.次の関数で検出できます.
    var hasEnumShadowsQuirk = function(){
        var o = { toString : function(){} }
        var count = 0;
        for (var prop in o){
            if (prop == "toString"){
                count++;
            }
        }
        return (count > 1);
    }();
    
    ブラウザにこのバグがある場合、for-inループを使用してカスタムtoString()メソッドを持つオブジェクトを列挙すると、2つのtoStringのインスタンスが返されます.