码迷,mamicode.com
首页 > 其他好文 > 详细

高程第9章 客户端检测

时间:2015-12-03 02:15:21      阅读:251      评论:0      收藏:0      [点我收藏+]

标签:

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循环中返回被隐藏的属性.怪癖检测通常涉及到运行一小段代码,然后确定浏览器是否存在某个怪癖.由于怪癖检测与能力检测相比效率更低,因此应该只在某个怪癖会干扰脚本运行的情况下使用.怪癖检测无法精确地检测特定的浏览器和版本.

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

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

高程第9章 客户端检测

标签:

原文地址:http://www.cnblogs.com/sunshinegirl-7/p/5014908.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!