1. 能力检测(特性检测)——检测浏览器是否具有某些特性
a.先检测达成目的最常用的特性,保证代码最优化
b.必须检测实际使用的特性
1)更可靠的能力检测:能力检测中仅检测某个特性是否存在是不可靠的,更可靠的方式是检测确定他是否会真正按照我们想要的方式行事,(列如我们检测某个对象是否支持排序,仅检测object.sort是不够的,这只能说明object包含sort属性,更靠谱的检测方式是检测object是否具有sort()方法),我们通常使用typeof来检测是否支持相应的功能,在可能的情况下尽可能使用typeof进行能力检测。
目前比较靠谱的能力检测方式:
//作者:Peter Michaux
function isHostMethod(object, property) {
var t = typeof object[property];
return t=='function' ||
(!!(t=='object' && object[property])) ||
t=='unknown';
}
这种方式考虑到了浏览器的怪异行为。
2)能力检测不能用来做浏览器检测
2.怪癖检测——检测浏览器存在什么缺陷
一般我们建议仅检测那些对自己有影响的“怪癖”,而且最好在脚本一开始就执行此类检测,以便尽早解决问题。
3.用户代理检测
· 1)用户代理字符串的历史:由于最处开发浏览器的公司产品代号Mozilla(最早开发的是美国NCSA(国家超级计算机中心),产品叫Mosaic),将其用户代理设为Mosaic/版本号...,该产品被广泛认可,许多服务器在提供服务时都会检测这个字段来确定浏览器,所以导致后续的IE、Firefox、Safari、Chrome等浏览器为了想服务器伪装自己,导致后面的浏览器用户代理字符串产品名称与HTTP规范有很大的差异。
2)用户代理字符串检测
a.检测呈现引擎:一般情况下,我们知道呈现引擎和要求的最低限度的版本号就足以决定正确的操作方法了,我们不推荐针对具体得了浏览器版本号做检测。
五大引擎的检测顺序是:Oper、WebKit、KHTML、Gecko、IE
1 var client = function(){ //在全局作用域中减少不必要的变量,采用增强模块模式来封装 2 var engine = { 3 //呈现引擎 4 ie: 0, 5 gecko: 0, 6 webkit: 0, 7 khtml: 0, 8 opera: 0, 9 //具体的版本号 10 ver: null 11 }; 12 //在此检测呈现引擎、平台和设备 13 return { 14 engine : engine 15 }; 16 }(); 17 18 var ua = navigator.userAgent; 19 if (window.opera){ 20 engine.ver = window.opera.version(); 21 engine.opera = parseFloat(engine.ver); 22 } else if (/AppleWebKit/(S+)/.test(ua)){ 23 engine.ver = RegExp["$1"]; 24 engine.webkit = parseFloat(engine.ver); 25 } else if (/KHTML/(S+)/.test(ua)) { 26 engine.ver = RegExp["$1"]; 27 engine.khtml = parseFloat(engine.ver); 28 } else if (/rv:([^)]+)) Gecko/d{8}/.test(ua)){ 29 engine.ver = RegExp["$1"]; 30 engine.gecko = parseFloat(engine.ver); 31 } else if (/MSIE ([^;]+)/.test(ua)){ 32 engine.ver = RegExp["$1"]; 33 engine.ie = parseFloat(engine.ver); 34 }
b.检测浏览器 —— 大多数情况下识别了浏览器的呈现引擎就足以为我们采取正确的操作提供依据了。可是,只有呈现引擎还不能说明存在所需的JavaScript 功能。苹果公司的Safari 浏览器和谷歌公司的Chrome 浏览器都使用WebKit 作为呈现引擎,但它们的JavaScript 引擎却不一样。
大多数浏览器与呈现引擎密切相关,所以检测浏览器的代码与检测呈现引擎的代码是混合在一起的。
1 var client = funciton(){ 2 var engine= { 3 //呈现引擎 4 ie: 0, 5 gecko: 0, 6 webkit: 0, 7 khtml: 0, 8 opera: 0, 9 //具体的版本 10 ver: null 11 }; 12 var browser = { 13 //浏览器 14 ie: 0, 15 firefox: 0, 16 safari: 0, 17 konq: 0, 18 opera: 0, 19 chrome: 0, 20 //具体的版本 21 ver: null 22 }; 23 return { 24 engine: engine, 25 browser: browser 26 }; 27 }(); 28 29 //检测呈现引擎及浏览器 30 var ua = navigator.userAgent; 31 if (window.opera){ 32 engine.ver = browser.ver = window.opera.version(); 33 engine.opera = browser.opera = parseFloat(engine.ver); 34 } else if (/AppleWebKit/(S+)/.test(ua)){ 35 engine.ver = RegExp["$1"]; 36 engine.webkit = parseFloat(engine.ver); 37 //确定是Chrome 还是Safari 38 if (/Chrome/(S+)/.test(ua)){ 39 browser.ver = RegExp["$1"]; 40 browser.chrome = parseFloat(browser.ver); 41 } else if (/Version/(S+)/.test(ua)){ 42 browser.ver = RegExp["$1"]; 43 browser.safari = parseFloat(browser.ver); 44 } else { 45 //近似地确定版本号 46 var safariVersion = 1; 47 if (engine.webkit < 100){ 48 safariVersion = 1; 49 } else if (engine.webkit < 312){ 50 safariVersion = 1.2; 51 } else if (engine.webkit < 412){ 52 safariVersion = 1.3; 53 } else { 54 safariVersion = 2; 55 } 56 browser.safari = browser.ver = safariVersion; 57 } 58 } else if (/KHTML/(S+)/.test(ua) || /Konqueror/([^;]+)/.test(ua)){ 59 engine.ver = browser.ver = RegExp["$1"]; 60 engine.khtml = browser.konq = parseFloat(engine.ver); 61 } else if (/rv:([^)]+)) Gecko/d{8}/.test(ua)){ 62 engine.ver = RegExp["$1"]; 63 engine.gecko = parseFloat(engine.ver); 64 //确定是不是Firefox 65 if (/Firefox/(S+)/.test(ua)){ 66 browser.ver = RegExp["$1"]; 67 browser.firefox = parseFloat(browser.ver); 68 } 69 } else if (/MSIE ([^;]+)/.test(ua)){ 70 engine.ver = browser.ver = RegExp["$1"]; 71 engine.ie = browser.ie = parseFloat(engine.ver); 72 }
c.识别平台——在某些情况下需要考虑不同的平台,因为那些具有各种平台版本的浏览器(如Safari、Firefox、Opera)在不同的平台下可能会有不同的问题。
1 var client = function(){ 2 var engine = { 3 //呈现引擎 4 ie: 0, 5 gecko: 0, 6 webkit: 0, 7 khtml: 0, 8 opera: 0, 9 //具体的版本号 10 ver: null 11 }; 12 var browser = { 13 //浏览器 14 ie: 0, 15 firefox: 0, 16 safari: 0, 17 konq: 0, 18 opera: 0, 19 chrome: 0, 20 //具体的版本号 21 ver: null 22 }; 23 var system = { 24 win: false, 25 mac: false, 26 x11: false 27 }; 28 //在此检测呈现引擎、平台和设备 29 return { 30 engine: engine, 31 browser: browser, 32 system: system 33 }; 34 }(); 35 36 //平台检测代码 37 var p = navigator.platform; 38 system.win = p.indexOf("Win") == 0; 39 system.mac = p.indexOf("Mac") == 0; 40 system.x11 = (p.indexOf("X11") == 0) || (p.indexOf("Linux") == 0);
d.识别Windows操作系统(一般很少使用)
结合上面,我们将相应的windows版本信息存储在system.win 中,由于非空字符串会转换为布尔值true,因此可以将client.system.win 作为布尔值用在if 语句中。而在需要更多有关操作系统的信息时,则可以使用其中保存的字符串值。
1 if (system.win){ 2 if (/Win(?:dows )?([^do]{2})s?(d+.d+)?/.test(ua)){ 3 if (RegExp["$1"] == "NT"){ 4 switch(RegExp["$2"]){ 5 case "5.0": 6 system.win = "2000"; 7 break; 8 case "5.1": 9 system.win = "XP"; 10 break; 11 case "6.0": 12 system.win = "Vista"; 13 break; 14 case "6.1": 15 system.win = "7"; 16 break; 17 default: 18 system.win = "NT"; 19 break; 20 } 21 } else if (RegExp["$1"] == "9x"){ 22 system.win = "ME"; 23 } else { 24 system.win = RegExp["$1"]; 25 } 26 } 27 }
e.识别移动设备
1 //检测iphone、ipod、ipad 2 system.iphone = ua.indexOf("iPhone") > -1; 3 system.ipod = ua.indexOf("iPod") > -1; 4 system.ipad = ua.indexOf("iPad") > -1; 5 //检测IOS版本 6 if (system.mac && ua.indexOf("Mobile") > -1){ 7 if (/CPU (?:iPhone )?OS (d+_d+)/.test(ua)){ 8 system.ios = parseFloat(RegExp.$1.replace("_", ".")); 9 } else { 10 system.ios = 2; //不能真正检测出来,所以只能猜测 11 } 12 } 13 //检测Android 版本 14 if (/Android (d+.d+)/.test(ua)){ 15 system.android = parseFloat(RegExp.$1); 16 }
f.识别游戏系统——主要的两大游戏系统:任天堂Wii和Playstation3
1 system.wii = ua.indexOf("Wii") > -1; 2 system.ps = /playstation/i.test(ua);
在决定使用哪种客户端检测方法时,一般应优先考虑使用能力检测。怪癖检测是确定应该如何处理代码的第二选择。而用户代理检测则是客户端检测的最后一种方案,因为这种方法对用户代理字符串具有很强的依赖性。