第9章 客户端检测
9.1 能力检测(特性检测)
能力检测的目标不是识别特定的浏览器,而是识别浏览器的能力。采用这种方式不必顾及特定的浏览器如何如何,只要确定浏览器支持特定的能力,就可以给出解决方案。能力检测的基本模式如下:
if(object.propertyInQuestion){
//使用object.propertyInQuestion
}
举例来说,IE5及之前的版本不支持document.getElemengById()这个方法,尽管可以使用非标准的document.all属性实现同样的目的,但IE的早期版本中确实不存在document.getElemengById()。于是,有了下面示例中的写法:
function getElementById(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 by id!");
}
}
先检测达成目的的最常用的特性。这样做可以保证代码最优化,保证在多数情况下避免多个测试条件。
还有一个重要的概念就是必须测试实际要用到的特性,一个特性存在不一定意味着另一个特性也存在。
function getWindowWidth() {
if (document.all) { //假设是IE
return document.documentElement.clientWidth; //错误的用法!!!
} else {
return window.innerWidth;
}
}
无法根据一个特性就确定是否是某个浏览器,上述代码测试了`document.all`存在也不能确定浏览器是IE。实际上,也可能是Opera,Opera支持`window.innerWidth`,也只支持`document.all`。
更可靠的能力检测
在可能的情况下,应尽量使用typeof进行能力检测。
但是,即使使用typeof检测,对于IE8和更低的版本来说,其行为也是不标准的,因为IE8及之前DOM对象都是通过COM而非JScript实现的,因此一些有关DOM操作的函数使用typeof检测时会返回“Object”而非“function”。
能力检测,不是浏览器检测
检测某个或者某几个特性并不能够确定浏览器,下面给出的这段代码(或者与之差不多的代码),可以在许多网站中看到,这种“浏览器检测”代码就是错误的依赖了能力检测的典型示例:
//错误!还不够具体
var isFirefox = !!(navigator.vendor &&navigator.vendorSub);
//错误!假设过头了
var isEE = !!(document.all && document.uniqueID);
双逻辑非操作符得到布尔值:比先存储后访问的效果更好。
在实际开发中,应该把能力检测作为确定下一步解决方案的依据,而不是用它来判断用户使用的是什么浏览器。
9.2 怪癖检测(quirks detection)
怪癖检测的目的是识别浏览器的特殊行为。但与能力检测确认浏览器支持什么能力不同,怪癖检测想要知道浏览器有什么缺陷(“怪癖”也就是bug)。这通常需要运行一小段代码以确定某一特性无法正常工作。例如IE8及更低版本中如果某个实例属性与标记为[[DontEnum]]的某个原型属性同名,那么该实例属性将无法出现在for-in循环中;又比如Safari3以前的版本中会枚举被隐藏的属性……
一般说来,“怪癖”都是个别浏览器所独有的,而且通常被划归为bug。在相关浏览器的新版本中,这些问题不一定会被修复,由于检测怪癖涉及到运行代码,因此建议最好脚本一开始就执行此类检测,而且只检测对所写代码有直接影响的“怪癖”。
9.3用户代理检测
用户代理字符串的历史
Firefox(Netscape)使用的呈现引擎是Gecko,Safari、Chrome浏览器使用的是Webkit,konqueror浏览器的呈现引擎是KHTML。
IOS和Android使用的是Webkit。
用户代理字符串检测技术
- 识别呈现引擎:五大呈现引擎有IE、Gecko、Webkit、KHTML和Opera。
- 检测顺序很重要:Opera-Webkit-KHTML-Gecko-IE
- 识别浏览器
- 识别平台 navigator.platform
- 识别windows操作系统
- 识别移动设备
- 识别游戏系统
完整的代码
使用方法
用户代理检测是最后的选择。只要可能,都应该首先进行能力检测和怪癖检测。
用户代理检测一般适用于如下情况:
- 不能直接准确地使用能力检测或者怪癖检测。例如:某些浏览器实现了为将来功能预留的存根(stub)函数。在这种情况下,仅测试相应的函数是否存在还得不到足够的信息。
- 同一款浏览器在不同的平台下具备不同的能力。这时候就有必要确定浏览器位于哪个平台下。
- 为了跟踪分析等目的需要知道确切的浏览器。
本文探讨了浏览器检测的不同方式,包括能力检测、怪癖检测和用户代理检测,并解释了每种方式的特点及其适用场景。
5892

被折叠的 条评论
为什么被折叠?



