检测 Web 客户端的手段很多,而且各有利弊,但最重要的是,不到万不得已,就不要使用客户端检测。
只要能够找到更通用的方法,就应该优先采用更通用的方法。
一言而蔽之,先设计最通用的方案,然后再使用特定于浏览器的技术增强该方案。
一、能力检测
最常用也最为人们广泛接受的客户端检测形式是能力检测(又称特性检测)。能力检测的目标不是识别特定的浏览器,而是识别浏览器的能力。采用这种方式不必顾忌特定的浏览器如何,只要确定浏览器支持特定的能力,就可以给出解决方案。
能力检测的基本模式如下:
if( object.propertyInQuestion){
//使用 object.propertyInQuestion
}
两个重要的概念:
第一个概念是先检测达成目的的最常用的特性。先检测最常用的特性,可以保证代码最优化,因为在多数情况下都可以避免测试多个条件。
第二个概念是必须测试实际要用到的特性。一个特性存在,不一定意味着另一个特性也存在。
检测某个或某几个特性并不能够确定浏览器。实际上,根据浏览器不同将能力组合起来是更可取的方式。
如果知道自己的应用程序需要使用某些特定的浏览器特性,那么最好是一次性检测所有相关特性,而不要分别检测。
//确定浏览器是否支持 Netscape 风格的插件
var hasNSPlugins = !!(navigator.plugins && navigator.plugins.length );
//确定浏览器是否具有 DOM1 级规定的能力
var hasDOM1 = !!(document.getElementById && document.createElement
&& document.getElementByTagName);
以上两个例子,一个检测是否支持 Netscape 风格的产检;另一个检测浏览器是否具备DOM1 级所规定的能力。所得到的布尔值可以在以后继续使用,从而节省重新检测能力的时间。
在实际开发中,应该将能力检测作为确定下一步解决方案的依据,而不是用它来判断用户使用的是什么浏览器。
二、怪癖检测
与能力检测类似,怪癖检测(quirks detection)的目标是识别浏览器的特殊行为。
但与能力检测不同,怪癖检测是想要知道浏览器存在什么缺陷。这个通常要运行一小段代码,以确定某一特性不能正常工作。
例如,IE中存在的一个 bug ,即如果某个实例属性与标记为 [[DontEnum]] 的某个原型属性同名,那么该实例属性将不会出现在 fon-in 循环当中。可以使用如下代码来检测这种“怪癖”:
var hasDontEnumQuirk = function(){
var o = { toString : function(){}};
for( var prop in o){
if( prop == "toString"){
return false;
}
}
return true;
}();
以上代码通过一个匿名函数来测试该“怪癖”,函数中创建了一个带有 toString() 方法的对象。在正确的 ECMAScript 实现中,toString 应该在 for-in 循环中作为属性返回。
另一个经常要检测的"怪癖"是safari 3.0 以前版本会美剧被隐藏的属性。可以用一下函数来检测:
var hasEnumShadownsQuirk = function(){
var o = { toString : functionn(){} };
var count = 0;
for( var prop in o){
if( prop == "toString"){
count++;
}
}
return (count > 1);
}();
如果浏览器存在这个bug,那么使用 for-in 循环枚举带有自定义的toString()方法的对象,就会返回两个 toString 的实例。
一般来说,“怪癖”都是个别浏览器所独有的,而且通常被归为 bug。
在相关浏览器的信版本中,这些问题可能会也可能不会被修复。由于检测“怪癖”涉及运行代码,因此建议仅检测那些对你有直接影响的“怪癖”,而且最好在脚本一开始就执行此类检测,以便尽早解决问题。
三、用户代理检测
第三种,也是争议最大的一种客户端检测技术叫用户代理检测。
用户代理检测通过检测用户代理字符串来确定实际使用的浏览器。
在每一次HTTP请求过程中,用户代理字符串是作为响应首部发送的,而该字符串可以通过 JavaScript 的 navigator.userAgent 属性访问。
在服务器端,通过检测用户代理字符串来确定用户使用的浏览器是一种常用而且广为接受的做法。
而在客户端,用户代理检测一般被当作一种万不得已才使用的做法,其优先级排在能力检测和怪癖检测之后。
一、用户代理字符串检测技术
1)识别呈现引擎
确切的知道浏览器的名字和版本号不如确定他们使用的是什么呈现引擎。如果Firefox、Camino 和 Netsacpe 都使用相同版本的 Gecko ,那么他们一定支持相同的特性。
类似的,不管是什么浏览器,只要它跟 Safari 3 使用的是同一个版本的 WebKit,那么该浏览器也就跟 Safari 3 具备同样的功能。
因此,我们需要编写的脚本将主要检测五大呈现引擎: IE、Gecko、WebKit、KHTML 和 Opera。
为了不在全局作用域中添加多余的变量,我们将使用模块增强模式来封装检测脚本。
检测到一个呈现引擎后,其 client.engine 中对应的属性将被设置成一个大于 0 的值,该值可以转换成布尔值的 true。这样就可以在 if 语句中检测相应的属性,以确定当前使用的呈现引擎,连具体的版本号都不需要考虑。
鉴于每个属性都包含一个浮点数值,因此有可能丢失某些版本信息。例如,将字符串"1.8.1"传入 parseFloat() 后悔得到数值 1.8。不过,在必要的时候,可以检测 ver 属性,该属性中保存着完整的版本信息。
正确的识别呈现引擎关键是检测顺序要正确。
首先应该检测的是 Opera
if ( window.opera ){
engine.ver = window.opera.version();
engine.opera = parseFloat( engine.ver );
}
其次检测的事 WebKit
var ua = navigator.userAgent;
if ( window.opera ){
engine.ver = window.opera.version();
engine.opera = parseFloat( engine.ver );
} else if ( /AppleWebKit\/(\S+)/.test(ua)){
engine.ver = RegExp["$1"];
engine.webkit = parseFloat(engine.ver);
}
接下来测试 KHTML
var ua = navigator.userAgent;
if ( window.opera ){
engine.ver = window.opera.version();
engine.opera = parseFloat( engine.ver );
} else if ( /AppleWebKit\/(\S+)/.test(ua)){
engine.ver = RegExp["$1"];
engine.webkit = parseFloat(engine.ver);
} else if ( /KHTML\/(\S+)/.test(ua) || /Konqueror\/([^;]+)/.test(ua)){
engine.ver = RegExp["$1"];
engine.khtml = parseFloat(engine.ver);
}
然后是 Gecko
var ua = navigator.userAgent;
if ( window.opera ){
engine.ver = window.opera.version();
engine.opera = parseFloat( engine.ver );
} else if ( /AppleWebKit\/(\S+)/.test(ua)){
engine.ver = RegExp["$1"];
engine.webkit = parseFloat(engine.ver);
} else if ( /KHTML\/(\S+)/.test(ua) || /Konqueror\/([^;]+)/.test(ua)){
engine.ver = RegExp["$1"];
engine.khtml = parseFloat(engine.ver);
} else if ( /rv:([^\)]+)\) Gecko\/\d{8}/.test(ua)){
engine.ver = RegExp["$1"];
engine.gecko = parseFloat(engine.ver);
}
最后一个就是ie了
var ua = navigator.userAgent;
if ( window.opera ){
engine.ver = window.opera.version();
engine.opera = parseFloat( engine.ver );
} else if ( /AppleWebKit\/(\S+)/.test(ua)){
engine.ver = RegExp["$1"];
engine.webkit = parseFloat(engine.ver);
} else if ( /KHTML\/(\S+)/.test(ua) || /Konqueror\/([^;]+)/.test(ua)){
engine.ver = RegExp["$1"];
engine.khtml = parseFloat(engine.ver);
} else if ( /rv:([^\)]+)\) Gecko\/\d{8}/.test(ua)){
engine.ver = RegExp["$1"];
engine.gecko = parseFloat(engine.ver);
} else if (/MSIE ([^;]+)/.test(ua)){
engine.ver = browser.ver = RegExp["$1"];
engine.ie = browser.ie = parseFloat(engine.ver);
}
2)识别浏览器
大多数情况下,识别了浏览器的呈现引擎就足以为我们采取正确的操作提供依据了。可是,只有呈现引擎还不恩能够说明存在所需的JavaScript功能。
var client = function(){
//呈现引擎
var engine = {
ie : 0,
gecko : 0,
webkit : 0,
khtml : 0,
opera : 0,
//具体的版本号
ver : null
};
var browser = {
//浏览器
ie : 0,
firefox : 0,
konq : 0,
opera : 0,
chrome : 0,
safari : 0,
//具体的版本
ver : null
};
//再次检测呈现引擎、平台和设备
return {
engine : engine,
browser : browser
};
}();
由于大多数浏览器与其呈现引擎密切相关,所以下面实力中检测浏览器的代码与呈现引擎的代码是混合在一起的

//检测呈现引擎及浏览器
var ua = navigator.userAgent;
if ( window.opera ){
engine.ver = window.opera.version();
engine.opera = parseFloat( engine.ver );
} else if ( /AppleWebKit\/(\S+)/.test(ua)){
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"];
borwser.safari = parseFloat(browser.ver);
} else {
//近似的确定版本号
var safariVersion = 1;
if (engine.webkit < 100 ){
safariVersion = 1;
} else if (engine.webkit < 312){
safariVersoin = 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 = RegExp["$1"];
engine.khtml = 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);
}

3、识别平台
很多时候,只要知道呈现引擎就可以编写出适合的代码了,但在有些情况下,平台可能是必须关注的问题。为了检测这些平台,需要再添加一个对象:
1 var client = function(){
2 //呈现引擎
3
4 var engine = {
5 ie : 0,
6 gecko : 0,
7 webkit : 0,
8 khtml : 0,
9 opera : 0,
10
11 //具体的版本号
12 ver : null
13 };
14
15 var browser = {
16 //浏览器
17 ie : 0,
18 firefox : 0,
19 konq : 0,
20 opera : 0,
21 chrome : 0,
22 safari : 0,
23
24 //具体的版本
25 ver : null
26 };
27
28 var system = {
29 win : false,
30 mac : false,
31 xll : false
32 };
33
34 //再次检测呈现引擎、平台和设备
35
36 return {
37 engine : engine,
38 browser : browser,
39 system : system
40 };
41 }();
42
43
44 var p = navigator.platform;
45 system.win = p.indexOf("Win") == 0;
46 systemp.mac = p.indexOf("Mac") == 0;
47 system.xll = (p.indexOf("Xll")) == 1 || (p.indexOf("Linux") == 0);
然后还有识别移动设备的
完整的代码如下:

1 var client = function(){
2 //呈现引擎
3
4 var engine = {
5 ie : 0,
6 gecko : 0,
7 webkit : 0,
8 khtml : 0,
9 opera : 0,
10
11 //具体的版本号
12 ver : null
13 };
14
15 var browser = {
16 //浏览器
17 ie : 0,
18 firefox : 0,
19 konq : 0,
20 opera : 0,
21 chrome : 0,
22 safari : 0,
23
24 //具体的版本
25 ver : null
26 };
27
28 //平台、设备和操作系统
29 var system = {
30 win : false,
31 mac : false,
32 xll : false,
33
34 //移动设备
35 iphone : false,
36 ipod : false,
37 nokiaN : false,
38 winMobile : false,
39 macMobile : false,
40
41 //游戏系统
42 wii : false,
43 ps : false
44 };
45
46 //检测呈现引擎及浏览器
47 var ua = navigator.userAgent;
48
49 if ( window.opera ){
50
51 engine.ver = window.opera.version();
52 engine.opera = parseFloat( engine.ver );
53
54 } else if ( /AppleWebKit\/(\S+)/.test(ua)){
55
56 engine.ver = RegExp["$1"];
57 engine.webkit = parseFloat(engine.ver);
58
59 //确定是Chrome 还是 Safari
60 if ( /Chrome\/(\S+)/.test(ua)){
61 browser.ver = RegExp["$1"];
62 browser.chrome = parseFloat(browser.ver);
63 } else if ( /Version\/(S+)/test(ua)){
64 browser.ver = RegExp["$1"];
65 borwser.safari = parseFloat(browser.ver);
66 } else {
67 //近似的确定版本号
68 var safariVersion = 1;
69
70 if (engine.webkit < 100 ){
71 safariVersion = 1;
72 } else if (engine.webkit < 312){
73 safariVersoin = 1.2;
74 } else if (engine.webkit < 412){
75 safariVersion = 1.3;
76 } else {
77 safariVersion = 2;
78 }
79
80 browser.safari = browser.ver = safariVersion;
81 }
82
83 } else if ( /KHTML\/(\S+)/.test(ua) || /Konqueror\/([^;]+)/.test(ua)){
84 engine.ver = RegExp["$1"];
85 engine.khtml = parseFloat(engine.ver);
86 } else if ( /rv:([^\)]+)\) Gecko\/\d{8}/.test(ua)){
87 engine.ver = RegExp["$1"];
88 engine.gecko = parseFloat(engine.ver);
89
90 //确定不是Firefox
91 if( /Firefox\/(\S+)/.test(ua)){
92 browser.ver = RegExp["$1"];
93 browser.firefox = parseFloat(browser.ver);
94 }
95
96 } else if (/MSIE ([^;]+)/.test(ua)){
97 engine.ver = browser.ver = RegExp["$1"];
98 engine.ie = browser.ie = parseFloat(engine.ver);
99 }
100
101 //检测浏览器
102 browser.ie = engine.ie;
103 browser.opera = engine.opera;
104
105 //检测平台
106 var p = navigator.platform;
107 system.win = p.indexOf("Win") == 0;
108 systemp.mac = p.indexOf("Mac") == 0;
109 system.xll = (p.indexOf("Xll")) == 1 || (p.indexOf("Linux") == 0);
110
111 //检测 Windows 操作系统
112 if( system.win){
113 if( /Win(?:dows)?([^do]{2})\s?(\d+\.\d+)?/.test(ua)){
114 if(RegExp["$1"] == "NT"){
115 switch(RegExp["$2"]){
116 case "5.0" :
117 system.win = "2000";
118 break;
119 case "5.1" :
120 system.win = "XP";
121 break;
122 case "6.0" :
123 system.win = "Vista";
124 break;
125 default :
126 system.win = "NT";
127 break;
128 }
129 } else if (RegExp["$1"] == "9x"){
130 system.win = "ME";
131 } else {
132 system.win = RegExp["$1"];
133 }
134 }
135 }
136
137 //移动设备
138 system.iphone = ua.indexOf("iphone") > -1;
139 system.ipod = ua.indexOf("iPod") > -1;
140 system.nokiaN = ua.indexOf("NokiaN") > -1;
141 system.winMobile = (system.win == "CE");
142 system.macMobile = (system.iphone || system.ipod);
143
144 //游戏系统
145 system.wii = ua.indexOf("Wii") > -1;
146 system.ps = /playstation/i.test(ua);
147
148 //再次检测呈现引擎、平台和设备
149
150 return {
151 engine : engine,
152 browser : browser,
153 system : system
154 };
155 }();

分享到:
相关推荐
这篇博客“js客户端检测”可能深入探讨了如何利用JavaScript进行这类检测。 首先,客户端检测通常包括以下几个方面: 1. **浏览器类型和版本**:JavaScript的`navigator.userAgent`属性提供了关于用户浏览器的信息...
JavaScript客户端验证是网页开发中必不可少的一环,它主要用于在用户提交数据前检查输入的有效性和格式,从而提高用户体验并减轻服务器端的压力。以下是一些常见的JavaScript验证函数及其详细说明: 1. 判断是否是...
"js检查客户端的jre版本"这个标题揭示了我们要探讨的核心技术点:如何利用JavaScript来检测用户的JRE版本。 首先,我们需要理解JavaScript与Java之间的关系。虽然它们都源自Sun Microsystems(现在是Oracle),但...
"Cookies.js - JavaScript 客户端的Cookie操作库" 进一步明确了这个库是Cookies.js,它是专门为JavaScript开发设计的,主要功能是在用户浏览器上执行Cookie的相关操作。作为客户端库,它使得开发者无需后端服务器...
JavaScript(简称JS)活体检测是一种基于纯HTML5技术实现的身份验证方法,它在HTTPS安全协议下运行,确保用户在安卓设备上进行身份验证时,能够有效地检测到真实的人脸,而不是静态的照片或其他非活体图像。...
JavaScript 获取客户端计算机硬件及系统信息 在网络应用中,获取客户端计算机硬件及系统信息是非常有价值的。通过 JavaScript,可以使用 WMI(Windows Management Instrumentation)来实现获取客户端计算机硬件及...
SIP-js客户端JS框架则是将SIP协议的功能集成到JavaScript中,允许开发者在Web浏览器环境中实现VoIP功能,比如进行语音通话、视频会议等。 在JavaScript世界中,SIP-js提供了API来创建、管理和控制SIP会话。它支持...
当页面编辑或运行提交时,出现“从客户端中检测到有潜在危险的request.form值”问题,该怎么办呢?如下图所示: 下面博主汇总出现这种错误的几种解决方法: 问题原因:由于在asp.net中,Request提交时出现有html...
浏览器的种类很多,每个浏览器都有呈现引擎,但是同一款浏览器的不同版本呈现引擎也不一定一样,这就会导致我们同一个页面在不同浏览器下出现差异,这时候客户端检测就成为
nw.js客户端更新模块是nw.js应用中的一个关键部分,它使得开发者能够方便地实现应用的自动更新功能,从而确保用户始终运行的是最新版本。 在nw.js应用中,客户端更新通常涉及到以下几个步骤: 1. **检测更新**:...
这个"javascript客户端验证和页面特效制作项目案例"旨在帮助学习者掌握JavaScript的核心概念,并将其应用于实际项目中,提升网页的交互性和用户体验。 首先,客户端验证是确保用户输入数据有效性的关键步骤。...
本文将详细介绍在客户端和服务器端使用JavaScript来判断文件是否存在的方式,并提供相应的示例代码。 客户端判断文件是否存在: 在客户端,我们可以利用Windows平台的ActiveX对象“Scripting.FileSystemObject”来...
JavaScript是一种广泛应用于客户端Web开发的脚本语言,它在浏览器环境中执行,为用户提供动态交互体验。本文将深入探讨JavaScript中的常用函数以及客户端验证技术。 首先,我们来看看JavaScript中的一些核心函数: ...
综上所述,JavaScript的客户端检测能力对于开发者来说是一个非常有用的技能,它可以帮助开发者针对不同的浏览器和设备提供更好的用户体验。然而,这项技能的掌握需要对各种浏览器和操作系统的UA字符串有深入的了解,...
客户端上经常需要处理用户输入的数据,特别是遇到价格,库存等数值型数据时..本Js就是针对这一情况特别处理..对文本框需加上: onkeyup 属性..详细使用参考文件
总结,这个主题覆盖了JavaScript客户端开发中的多个重要知识点,包括基本语法、DOM操作、事件处理、AJAX通信以及UI组件的实现,同时也关注了性能优化和安全性。通过学习和实践这些例子,开发者可以提升自己在创建...
北大青鸟的这门课程,"JavaScript客户端验证和页面特效制作",旨在深入讲解这两个主题,帮助学员掌握实际开发中的关键技能。 客户端验证是提高用户体验的重要手段,它允许在用户提交数据前就检查输入的有效性,减少...
在本文中,我们将探讨如何使用C#在服务器端开启WebSocket服务,并使用JavaScript在客户端进行连接和交互。 首先,我们需要了解C#中的WebSocket API。在.NET框架中,System.Net.WebSockets命名空间提供了用于实现...