JS第九章——客户端检测
能力检测(特性检测)
为了识别浏览器的能力
能力检测的基本模式:
document.getElementById()的DOM方法(IE5.0后)与document.all属性检测
如果该函数存在(不是未定义),则使用 该函数。否则,就要继续检测 document.all 是否存在,如果是,则使用它。如果上述两个特性都不存在(很有可能),则创建并抛出错误,表示这个函数无法使用。
测试所用到的特性时候,一个特性存在,不一定意味着另一个特性也存在
更加可靠的能力检测
DOM对象是宿主对象,IE及更早版本中的宿主对象是通过COM而非JScript 实现的。因此,document.createElement()函数确实是一个 COM 对象,所以 typeof 才会返回"object"。IE9纠正了这个问题,对所有 DOM方法都返回"function"
使用isHostMethod()方法,考虑到了浏览器的怪异行为,测试任何对象的某个特性是否存在比较可靠
能力检测,不是浏览器检测
检测浏览器的属性,使用一次性检测所有相关特性,节省重新检测能力的时间
使用了双逻辑非操作符来得到布尔值(比先存储后访问的效果更好)
在实际开发中,应该将能力检测作为确定下一步解决方案的依据,而不是用它来判断用户使用的是什么浏览器
怪癖检测
怪癖检测(quirks detection)的目标是识别浏览器的特殊行为
为了了解浏览器存在什么缺陷(“怪癖”也就是bug)
常用的怪癖检测
某个实例属性与[[Enumerable]]标记为 false 的某个原型属性同名,那么该实例属性将不会出现在 fon-in 循环当中


Safari 3以前版本会枚举被隐藏的属性

如果浏览器存在这个 bug,那么使用 for-in 循环枚举带有自定义的 toString()方法的对象,就 会返回两个 toString 的实例
仅检测那些有直接影响的“怪癖”,而且好在脚本一开始就执行此类检测,以便尽早解决问题
用户代理检测
用户代理检测通过检测用户代理字符串来确定实际使用的浏览器
在每一次 HTTP请求过程中,用户代理字符串是作为响应首部发送的, 而且该字符串可以通过 JavaScript的 navigator.userAgent 属性访问
电子欺骗(spoofing)指浏览器通过在自己的用户代理字符串加入一些错误或误导性信息,来达到欺骗服务器的目的
用户代理字符串的历史
HTTP规范(包括 1.0和 1.1版)明确规定,浏览器应该发送简短的用户代理字符串,指明浏览器的 名称和版本号。
用户代理字符串应该以一组产品的形式给出,字符串格式为:标识符/产品 版本号
早期的浏览器
Netscape 在坚持将产品名和版本号作为用户代理字符串开头的基础上,又在后面依次添加了语言、平台、加密类型的信息
Netscape Navigator 3和 Internet Explorer 3
由于当时的大多数浏览器嗅探程序只检测用户代理字符串中的产品名称部分,结果 IE 就成功地将 自己标识为 Mozilla,从而伪装成 Netscape Navigator。微软的这一做法招致了很多批评,因为它违反了 浏览器标识的惯例。更不规范的是,IE将真正的浏览器版本号插入到了字符串的中间
Netscape Communicator 4和 IE4~IE8
IE9运行在 IE7兼容模式下的用户代理字符串: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; Trident/5.0)
所有这些变化都是为了确保过去的用户代理检测脚本能够继续发挥作用,同时还能给新脚本提供更 丰富的信息
Gecko
Gecko是 Firefox的呈现引擎。当初的 Gecko是作为通用 Mozilla浏览器的一部分开发的,而第一个 采用 Gecko引擎的浏览器是 Netscape 6
Mozilla/Mozilla 版本号 (平台; 加密类型; 操作系统或 CPU; 语言; 预先发行版本) Gecko/Gecko 版本号 应用程序或产品/应用程序或产品版本号


WebKit
Mozilla/5.0
(平台; 加密类型; 操作系统或 CPU; 语言) AppleWebKit/AppleWebKit 版本号
(KHTML, like Gecko) Safari/Safari 版本号
Safari 3.0
Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en) AppleWebKit/522.15.5 (KHTML, like
Gecko) Version/3.0.3 Safari/522.15.5
Konqueror
与 KDE Linux集成的 Konqueror,是一款基于 KHTML开源呈现引擎的浏览器。尽管 Konqueror只 能在 Linux中使用,但它也有数量可观的用户。为确保大限度的兼容性,Konqueror效仿 IE选择了如 下用户代理字符串格式:
Mozilla/5.0 (compatible; Konqueror/ 版本号; 操作系统或 CPU )
Chrome
谷歌公司的 Chrome浏览器以 WebKit 作为呈现引擎,但使用了不同的 JavaScript引擎
Mozilla/5.0 ( 平台; 加密类型; 操作系统或 CPU; 语言) AppleWebKit/AppleWebKit 版本号 (KHTML,
like Gecko) Chrome/ Chrome 版本号 Safari/ Safari 版本
Opera
仅就用户代理字符串而言,Opera 应该是有争议的一款浏览器了。Opera 默认的用户代理字符串 是所有现代浏览器中合理的——正确地标识了自身及其版本号
Opera/ 版本号 (操作系统或 CPU; 加密类型) [语言]
Opera标识自身的另一种方式,就是把自己装扮成 Firefox或 IE。在这种隐瞒真实身份的情况下,用 户代理字符串实际上与其他浏览器返回的相同——既没有 Opera 字样,也不包含 Opera 版本信息。换 句话说,在启用了身份隐瞒功能的情况下,无法将 Opera和其他浏览器区别开来。另外,由于 Opera喜 欢在不告知用户的情况下针对站点来设置用户代理字符串,因此问题就更复杂化了。例如,打开 My Yahoo!站点(my.yahoo.com)会自动导致 Opera将自己装扮成 Firefox。如此一来,要想识别 Opera 就难上加难了。
在 Opera 7以前的版本中,Opera会解析 Windows操作系统字符串的含义。例如, Windows NT 5.1 实际上就是 Windows XP,因此 Opera 会在用户代理字符串中包含 Windows XP而非 Windows NT 5.1。为了与其他浏览器更兼容,Opera 7开始包含正式 的操作系统版本,而非解析后的版本
Opera 10又增加了 Presto 记号(Presto是 Opera的呈现引擎)和 Version 记号,后者用以保存实际的版本号
iOS和 Android
移动操作系统 iOS和 Android默认的浏览器都基于 WebKit,而且都像它们的桌面版一样,共享相同 的基本用户代理字符串格式
Mozilla/5.0 (平台; 加密类型; 操作系统或 CPU like Mac OS X; 语言) AppleWebKit/AppleWebKit 版本号 (KHTML, like Gecko) Version/浏览器版本号 Mobile/移动版本号 Safari/Safari 版本号
其余具体历史可在JS高级程序设计仔细阅读
用户代理字符串检测技术
利用相对版本号来检测特定浏览器

检测IE的版本号是否至少等于 6,如果是则执行相应操作
识别呈现引擎
主要检测五大呈现引擎:IE、Gecko、WebKit、KHTML和 Opera

这里声明了一个名为 client 的全局变量,用于保存相关信息。匿名函数内部定义了一个局部变量 engine,它是一个包含默认设置的对象字面量。在这个对象字面量中,每个呈现引擎都对应着一个属 性,属性的值默认为 0。如果检测到了哪个呈现引擎,那么就以浮点数值形式将该引擎的版本号写入相 应的属性。而呈现引擎的完整版本(是一个字符串),则被写入 ver 属性
检测WebKit
用户代理字符串中的"AppleWebKit"是独一无二的

WebKit 版本与 Safari版本的详细对应情况(可能有偏差)


检测KHTML
用户代理字符串中包含"Gecko",在排除 KHTML之前,无法准确检测基于 Gecko的浏览器
由于 Konqueror 3.1 及更 早版本中不包含 KHTML的版本,故而就要使用 Konqueror的版本来代替

排除了 WebKit 和 KHTML之后,就可以准确地检测 Gecko


最后检测IE引擎
IE的版本号位于字符串"MSIE"的后面、一个分号的前面

识别浏览器


对 Opera和 IE而言,browser 对象中的值等于 engine 对象中的值。对 Konqueror而言,browser. konq 和 browser.ver 属性分别等于 engine.khtml 和 engine.ver 属性;
为了检测 Chrome和 Safari,在检测引擎的代码中添加if语句。提取 Chrome的版本号时,需要查找字符串"Chrome/"并取得该字符串后面的数值。而提取 Safari 的版本号时,则需要查找字符串 "Version/"并取得其后的数值
在检测 Firefox的版本时,首先要找到字符串"Firefox/"

识别平台

Gecko的早期版本在所有 Windows平台中都返回字符串"Windows",在所有 Mac平 台中则都返回字符串"Macintosh"。Firefox 1 确定了 navigator.platform 的值。
识别 Windows操作系统

不同浏览器在表示不同的 Windows操作系统时给出的不同字符串

如果 system.win 的值为 true,那么就使用这个正则表达式从用户代理字符串中提取具体的信息
进一步检测平台

识别移动设备
第一步是为要检测的所有移动设备添加属性

之后检测各个移动设备
识别游戏系统
检测设备前需要先为 client.system 中添加适当的属性


之后检测游戏系统

完整的代码




使用方法





