本章内容
- 使用能力检测
- 用户代理检测的历史
- 选择检测方式
9.1 能力检测
能力检测的基本模式如下:
if (object.propertyInQuestion) {
//使用 object.propertyInQuestion
}
举例子,IE 5.0 之前版本不支持document.getElementById()
这个 DOM 方法。
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 retrieve element");
}
}
9.1.1 更可靠的能力检测
能力检测对于想知道某个特性是否会按照适当方式行事(而不仅仅是某个特性存在)非常有用。来看下面的函数,它用来确定一个对象是否支持排序。
//不要这样做!这不是能力检测--只检测了是否存在相应的方法
function isSortable(object) {
return !! object.sort;
}
更好的方式是检测sort
是不是一个函数。
//这样更好,检查 sort 是不是函数
function isSortable(object) {
return typeof object.sort == "function";
}
9.1.2 能力检测,不是浏览器检测
检测某个或某几个特性并不能够确定浏览器。
实际上,根据浏览器不同将能力组合起来是更可取的方式。如果你知道自己的应用程序需要使用某些特定的浏览器特性,那么最好是一次性检测所有相关特性,而不是分别检测。
在实际开发中,应该将能力检测作为确定下一步解决方案的依据,而不是用它来判断用户使用的是什么浏览器。
9.2 怪癖检测
怪癖检测的目标是识别浏览器的特殊行为。但与能力检测确认浏览器支持什么能力不同,怪癖检测是想要知道浏览器存在什么缺陷。通常需要运行一小段代码,以确定某一特性不能正常工作。
9.3 用户代理检测
第三种,也是争议最大的一种客户端检测技术叫做用户代理检测。用户代理检测通过检测用户代理字符串来确定实际使用的浏览器。在每一次 HTTP 请求过程中,用户代理字符串是作为响应首部发送的,而且该字符串可以通过 JavaScript 的navigator.userAgent
属性访问。在服务器端,通过检测用户代理字符串来确定用户使用的浏览器是一种常用而且广为接受的做法。而在客户端,用户代理检测一般被当作一种万不得已才用的做法,其优先级排在能力检测和怪癖检测之后。
9.3.1 用户代理字符串的历史
9.3.2 用户代理字符串检测技术
一般情况下,知道呈现引擎和最低限度的版本就足以决定正确的操作方法了。
- 识别呈现引擎
我们要编写的脚本将主要检测五大呈现引擎:IE、Gecko、WebKit、KHTML 和 Opera。
检测脚本的基本代码结构如下所示:
var client = function () {
var engine = {
//呈现引擎
ie: 0,
gecko: 0,
webkit: 0,
khtml: 0,
opera: 0,
//具体的版本号
ver: null
};
//在此检测呈现引擎、平台和设备
return {
engine: engine
};
}();
在这个对象字面量中,每个呈现引擎都对应着一个属性,属性的值默认为 0。如果检测到了那个呈现引擎,那么就以浮点数值形式将该引擎的版本号写入相应的属性。而呈现引擎的完整版本,则被写入ver
属性。作这样的区分可以支持像下面这样编写代码:
if (client.engine.ie) {
//针对 IE 的代码
} else if (client.engine.gecko > 1.5){
if (client.engine.ver == "1.8.1") {
//针对这个版本执行某些操作
}
}
要正确地识别呈现引擎,关键是检测顺序要正确。为此,第一步就是识别 Opera,因为它的用户代理字符串有可能完全模仿其他浏览器。
if (window.opera) {
engine.ver = window.opera.version();
engine.opera = parseFloat(engine.ver);
}
应该放在第二位检测的呈现引擎是 WebKit。因为 WebKit 的用户代理字符串中包含"Gecko"
和"KHTML"
这两个子字符串,所以如果首先检测它们,很可能得出错误的结论。
不过,WebKit 的用户代理字符串中的“AppleWebKit”是独一无二的,因此检测这个字符串最合适。下面就是检测该字符串的示例代码:
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。同样,KHTML的用户代理字符串中也包含“Gecko”。KHTML 的版本号与 WebKit 的版本号在用户代理字符串中的格式差不多。因此可使用类似的正则表达式。
在排除了 WebKit 和 KHTML 之后,就可以准确地检测 Gecko 了。
最后一个要检测的就是 IE 了。版本号位于字符串“MSIE”的后面,一个分号的前面。
else if (/MSIE ([^;]+)/.test(ua) {
engine.ver = RegExp["$1"];
engine.ie = parseFloat(engine.ver);
}
- 识别浏览器
由于 Chrome 和 Safari 都使用 WebKit 作为呈现引擎,但它们的 JavaScript 引擎不一样。需要进一步识别。 - 识别平台
目前三大主流平台是 Windows、Mac 和 Unix(包括各种 Linux)。
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);
- 识别 Windows 操作系统
- 识别移动设备
- 识别游戏系统
9.3.3 完整的代码
9.3.4 使用方法
用户代理检测一般适用于下列情形。
- 不能直接准确地使用能力检测或怪癖检测。
- 同一款浏览器在不同平台下具备不同的能力。这时候,可能就有必要确定浏览器位于哪个平台下。
9.4 小结
客户端检测是 JavaScript 开发中最具争议的一个话题。下列方法是最经常使用的。
- 能力检测:在编写代码之前先检测特定浏览器的能力。
- 怪癖检测:怪癖实际上是浏览器实现中存在的 bug。
- 用户代理检测:通过检测用户代理字符串来识别浏览器等信息。
一般应优先考虑使用能力检测。怪癖检测是确定应该如何处理代码的第二选择。而用户代理检测应是最后一种方案。