zoukankan      html  css  js  c++  java
  • 高程第9章 客户端检测

    9.1 能力检测

    最常用也最为人们广泛接受的是客户端检测形式是能力检测(又称特性检测).能力检测的目标不是识别特定的浏览器,而是识别浏览器的能力.

    检测时,先检测最常用的特性可以保证代码的最优化,因为在多数情况下都可以避免测试多个条件.

    必须测试实际要用到的特性.一个特性存在,不一定意味着另一个特性也存在.

    9.1.1 更可靠的能力检测

    有时只检测方法存在还不行,更好的的方式是检测是不是一个函数.

    在可能的情况下,要尽量使用typeof进行能力检测.

    在IE8及之前的版本中,用typeof 检测document.createElement()时不是返回true,而是false,因为在IE8及之前它返回的是"object",而不是"function".DOM对象是宿主对象,IE及更早版本中的宿主对象是通过COM而非JScript实现的.IE9及之后,返回"function".

    目前使用isHostMethod()方法还是比较可靠的,不过并不能保证百分之百永远可靠.

    9.1.2 能力检测,不是浏览器检测

    在实际开发中,应该将能力检测作为确定下一步解决方案的依据,而不是用它来判断用户使用的是什么浏览器.

    9.2 怪癖检测

    与能力检测类似,怪癖检测的目标是识别浏览器的特殊行为.

    但与能力检测确认浏览器支持什么能力不同,怪癖检测是想要知道浏览器存在什么缺陷("怪癖"也就是bug).

    例如,IE8及更早版本中存在一个bug,即如果某个实例属性与[[Enumerable]]标记为false的某个原型属性同名,那么该实例属性将不会出现在for-in循环当中.

    另一个经常需要检测的"怪癖"是safari3以前版本会枚举被隐藏的属性.

    9.3 用户代理检测

    用户代理检测通过检测用户代理字符串来确定实际使用的浏览器.在每一次HTTP请求过程中,用户代理字符串是作为响应首部发送的,而且该字符串可以通过Javascript的navigator.userAgent属性访问.

    以下是完整的用户代理字符串检测脚本,包括检测呈现引擎,平台,window操作系统,移动设备和游戏系统.

    var client=function(){
        //呈现引擎
        var engine={
            ie:0,
            gecko:0,
            webkit:0,
            khtml:0,
            opera:0,
    
            //完整的版本号
            ver:null
        };
    
        //浏览器
        var browser={
            //主要浏览器
            ie:0,
            firefox:0,
            safari:0,
            konq:0,
            opera:0,
            chrome:0,
    
            //具体的版本号
            ver:null
        };
    
        //平台,设备和操作系统
        var system={
            win:false,
            mac:false,
            x11:false,
    
            //移动设备
            iphone:false,
            ipod:false,
            ipad:false,
            ios:false,
            android:false,
            nokiaN:false,
            winMobile:false,
    
            //游戏系统
            wii:false,
            ps:false
        };
    
        //检测呈现引擎和浏览器
        var ua=navigator.userAgent;
        if(window.opera){
            engine.ver=browser.ver=window.opera.version();
            engine.opera=browser.opera=parseFloat(engine.ver);
        }else if(/AppleWebKit/(S+)/.test(us)){
            engine.ver=RegExp("$1");
            engine.webkit=parseFloat(engine.ver);
    
            //确定是chrome还是safari
            if(/chrome/(S+)/.test(us)){
                browser.ver=RegExp["$1"];
                browser.chrome=parseFloat(browser.ver);
            }else if(/Version/(S+)/.test(ua)){
                browser.ver=RegExp["$1"];
                browser.safari=parseFloat(browser.ver);
            }else{
                //近似地确定版本号
                var safariVersion=1;
                if(engine.webkit<100){
                    safariVersion=1;
                }else if(engine.webkit<312){
                    safariVersion=1.2;
                }else if(engine.webkit<412){
                    safariVersion=1.3;
                }else{
                    safariVersion=2;
                }
    
                browser.safari=browser.ver=safariVersion;
            }
        }else if(/KHTML/(S+)/.test(ua)||/Konqueror/([^;]+)/.test(ua)){
            engine.ver=browser.ver=RegExp["$1"];
            engine.khtml=browser.konq=parseFloat(engine.ver);
        }else if(/rv:([^)]+))Gecko/d{8}/.test(ua)){
            engine.ver=RegExp["$1"];
            engine.gecko=parseFloat(engine.ver);
    
            //确定是不是Firefox
            if(/Firefox/(S+)/.test(ua)){
                browser.ver=RegExp["$1"];
                browser.firefox=parseFloat(browser.ver);
            }
        }else if(/MSIE([^;]+)/.test(ua)){
            engine.ver=browser.ver=RegExp["$1"];
            engine.ie=browser.ie=parseFloat(engine.ver);
        }
    
        //检测浏览器
        browser.ie=engine.ie;
        browser.opera=engine.opera;
    
        //检测平台
        var p=navigator.platform;
        system.win=p.indexOf("Win")==0;
        system.mac=p.indexOf("Mac")==0;
        system.x11=(p=="X11")||(p.indexOf("Linux")==0);
    
        //检测Windows操作系统
        if(system.win){
            if(/Win(?:dows)?([^do]{2})s?(d+)?/.test(ua)){
                if(RegExp["$1"]=="NT"){
                    switch(RegExp["$2"]){
                        case "5.0":
                            system.win="2000";
                            break;
                        case "5.1":
                            system.win="XP";
                            break;
                        case "6.0":
                            system.win="Vista";
                            break;
                        case "6.1":
                            system.win="7";
                            break;
                        default:
                            system.win="NT";
                            break;
                    }
                }else if(RegExp["$1"]=="9x"){
                    system.win="ME";
                }else{
                    system.win=RegExp["$1"];
                }
            }
        }
    
        //移动调协
        system.iphone=ua.indexOf("iphone")>-1;
        system.ipod=ua.indexOf("iPod")>-1;
        system.ipad=ua.indexOf("iPad")>-1;
        system.nokiaN=ua.indexOf("NokiaN")>-1;
    
        //window mobile
        if(system.win=="CE"){
            system.winMobile==system.win;
        }else if(system.win=="Ph"){
            if(/Windows Phone OS (d+.d+)/.test(ua)){
                system.win="Phone";
                system.winMobile=parseFloat(RegExp["$1"]);
            }
        }
    
        //检测ios版本
        if(system.mac&&ua.indexOf("mobile")>-1){
            if(/CPU(?:iPhone)?OS(d+_d+)/.test(ua)){
                system.ios=parseFloat(RegExp.$1.replace("_","."));
            }else{
                system.ios=2;//不能真正检测出来,所以只能猜测
            }
        }
    
        //检测Android版本
        if(/Android(d+.d+)/.test(ua)){
            system.android=parseFloat(RegExp.$1);
        }
    
        //游戏系统
        system.wii=ua.indexOf("Wii")>-1;
        system.ps=/playstation/i.test(ua);
    
        //返回这些对象
        return {
            engine:engine,
            browser:browser,
            system:system
        };
    }();

    用户代理检测一般适用于下列情形:

    不能直接准确地使用能力检测或怪癖检测.

    同一款浏览器在不同平台下具备不同的能力.这时候,可能就有必要确定浏览器位于哪个平台下.

    为了跟踪分析等目的需要知道确切的浏览器.

    9.4 小结

    能力检测:在编写代码之前先检测特定浏览器的能力.例如,脚本在调用某个函数之前,可能要先检测该函数是否存在.能力检测无法精确地检测特定的浏览器和版本.

    怪癖检测:怪癖实际上是浏览器实现中存在的bug,例如早期WebKit中就存在一个怪癖,即它会在for-in循环中返回被隐藏的属性.怪癖检测通常涉及到运行一小段代码,然后确定浏览器是否存在某个怪癖.由于怪癖检测与能力检测相比效率更低,因此应该只在某个怪癖会干扰脚本运行的情况下使用.怪癖检测无法精确地检测特定的浏览器和版本.

    用户代理检测:通过检测用户代理字符串来识别浏览器.用户代理字符串中包含大量与浏览器有关的信息,包括浏览器,平台,操作系统及浏览器版本.

    在决定使用哪种客户端检测方法时,一般应优先考虑使用能力检测.怪癖检测是确定应该如何处理代码的第二选择.而用户代理检测则是客户端检测的最后一种方案,因为这种方法对用户代理字符串具有很强的依赖性.

  • 相关阅读:
    python 基于gevent协程实现socket并发
    python asyncio
    python 池 协程
    python
    python 守护进程
    python 线程 threading模块
    python 安装Django失败处理
    python 队列
    python 锁
    继承,抽象类,多态,封装
  • 原文地址:https://www.cnblogs.com/sunshinegirl-7/p/5014908.html
Copyright © 2011-2022 走看看