1.能力检测
//能力检测的目标不是识别浏览器,而是识别浏览器的能力。它对于想知道某个特性是否会按照适当方式行事(而不仅仅是某个特性存在)非常有用。 //采用这种方式不必顾忌特定的浏览器如何如何,只要确定浏览器支持特定的能力,就可以给出解决方案。能力检测基本模式如下: if(object.propertyInQuestion){ //使用object.propertyInQuestion } //例如,IE5.0之前的版本不支持document.getElementById(),可以使用document.all()实现相同的目的。 function getElement(id){ if(document.getElementById){ return document.getElementById(id); }else if(document.all){ return document.all(id); }else{ throw new Error("No way to retrive element !") } } //在可能的情况下,要尽量使用typeof进行能力检测。 //isHostMethod()用于在浏览器环境下测试任何对象的某个特性是否存在 function isHostMethod(object,property){ var t = typeof object[property]; return t == "function" || (!!(t == "object" && object[property])) || t == "unkown" ; } result = isHostMethod(xhr,"open");//true //能力检测并不是浏览器检测。检测某个或某几个特性并不能确定浏览器。 //确定浏览器是否支持Netscape风格的插件 var hasNSPlugins = !!(navigator.plugins && navigator.plugins.length); //确定浏览器是否具有DOM1级规定的能力 var hasDOM1 = !!(document.getElementById && document.createElement && document.getElementsByTagName);
2.怪癖检测
//怪癖检测的目标是识别浏览器的特殊行为。是想要知道浏览器存在什么缺陷。通常需要运行一小段代码,以确定某一特性不能正常工作。 //如IE8及更早的版本中个存在一个bug,如果某个实例属性与[[Enumerable]]标记为false的某个原型属性同名,那么该实例属性将不会出现在for-in循环中。 var hasDontEnumQuirk = function(){ var o = { toString :function(){} }; for (var prop in o){ if(prop == "toString"){ return false; } } return true; }(); //Safari3以前版本会枚举被隐藏的属性。 function hasEnumShadowsQuirk = function(){ var o = { toString : function(){} }; var count = 0; for (var prop in o){ if(prop == "toString"){ count ++; } } return (count > 1); }();
3.用户代理检测
//通过检测用户代理字符串来确定实际使用的浏览器。在每一次HTTP请求过程中, //用户代理字符串(指明浏览器的名称和版本号)是作为响应头部发送的, //可以通过navigator.userAgent属性访问。(这种方式比较常用于服务端,客户端并不常用) //IE的引擎是Trident,Firefox->Gecko,Safari->Webkit(是KHTML的一个分支,后来独立出来) //Chrome->Webkit,Opera以前是Presto现在是Webkit //移动操作系统Android/iOS默认的浏览器都基于Webkit // 用户代理字符串检测技术 // client用于保存相关信息 var client = function(){ // 1.识别呈现引擎 var engine = { //呈现引擎 ie: 0, gecko: 0, webkit: 0, opera: 0, // 具体的版本号 ver: null }; //2.识别浏览器 var browser = { //浏览器 ie: 0, firefox: 0, safari: 0, konq: 0, opera: 0, chrome: 0, //具体的版本号 ver: null }; //3.识别平台 var system = { win: false, //表示window平台 mac: false, //表示Mac平台 xll: false //表示Unix平台 //5.识别移动设备 iphone: false, ipod: false, ipad: false, ios: false, andriod: false, nokiaN: false, winMobile: false, //6.识别游戏系统 Wii、PlayStation wii: false, ps: false }; var ua = navigator.userAgent; //要正确的识别呈现引擎,关键是检测顺序要正确。 if(window.opera){//第一步要识别的就是Opera,因为它的用户代理字符串有可能完全模仿其他浏览器。 engine.ver = browser.ver = window.opera.version; engine.opera = browser.opera = parseFloat(engine.ver); }else if(/AppleWebkit/(S+)/.test(ua)){//第二步是检测Webkit,因为它的用户代理字符串中包含“gecko”和“KHTML”,如果首先检测它可能会得出错误结论。 engine.ver = RegExp["$1"]; engine.webkit = parseFloat(engine.ver); //确定是chrome还是safari if(/Chrome/(S+)/.test(ua)){ 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)){//第三步要检测的是KHTML,同样KHTML也带有“Gecko”,所以在排除KHTML之前无法检测基于gecko的浏览器 engine.ver = browser.ver = RegExp["$1"]; engine.khtml = browser.konq = parseFloat(engine.ver); }else if(/rv:([^)]+)) Gecko/d{8}/.test(ua)){//第四步检测Gecko,因为它的用户代理字符串中会出现"rv:"。 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)){//最后一步检测IE 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.xll = (p.indexOf("Xll") == 0 || (p.indexOf("Linux") == 0)); //4.识别windows操作系统 if(system.win){ if(/Win(?:dows )?([^do]{2})s?(d+.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; if(system.win == "CE"){//检测Windows Phone system.winMobile = system.win; if(/Windows Phone OS (d+.d+)/.test(ua)){ system.win = "Phone"; system.winMobile = parseFloat(RegExp["$1"]); } } if(system.mac && ua.indexOf("Mobile") > -1){//检测iOS版本 if(/CPU (?:iPhone )?OS (d+_d+)/.test(ua)){ system.ios = parseFloat(RegExp.$1.replace("_",".")); }else{ system.ios = 2;//不能正真检测出来,只能猜 } } if(/Andriod (d+.d+)/.test(ua)){//检测Andriod版本 system.andriod = parseFloat(RegExp.$1); } //检测游戏系统 system.wii = ua.indexOf("Wii") > -1; system.ps = /playstation/i.test(ua); //在此检测呈现引擎、平台和设备 return { engine : engine, browser : browser, system : system }; }();