20-JavaScript高级程序设计-客户端检测

一、能力检测

最常用也最为人们广泛接受的客户端检测形式:能力检测(又称特性检测)。
能力检测的目标:不是识别特定的浏览器,而是识别浏览器的能力。

基本模式:

if (object.propertyInQuestion){ 
  //使用 object.propertyInQuestion
}

两个重要概念:
先检测达成目的的最常用的特性;
必须测试实际要用到的特性。

1. 更可靠的能力检测

尽量使用 typeof 进行能力检测。
注意:宿主对象使用 typeof 不一定返回合理的值,尤其是 IE 浏览器。
例如:在IE8及之前版本中,typeof document.createElement 返回的是object,而不是function。DOM 对象是宿主对象,IE8及更早版本中的宿主对象是通过 COM 而非 JavaScript 实现的。IE9纠正了,对所有 DOM 方法都返回function。

在浏览器环境下测试任何对象的某个特性是否存在,使用以下函数:

function isHostMethod(object, property) {
  var t = typeof object[property];
  return t=='function' || (!!(t=='object' && object[property])) || t=='unknown';
 }

这个函数以及其他类似函数,都不能百分之百地保证永远可靠。

2. 能力检测,不是浏览器检测

检测某个或某几个特性并不能够确定浏览器。
根据浏览器不同将能力组合起来是更可取的方式。

二、怪癖检测

怪癖检测(quirks detection)的目标:识别浏览器的特殊行为。
通常需要运行一小段代码,以确定某一特性不能正常工作。
例如:
1.E8 及更早版本中存在一个 bug,如果某个实例属性与[[Enumerable]]标记为 false 的某个原型属性同名,那么该实例属性将不会出现在 fon-in 循环当中。
2.Safari 3 以前版本会枚举被隐藏的属性。
一般来说,“怪癖”都是个别浏览器所独有的,而且通常被归为 bug。
由于检测“怪癖”涉及运行代码,因此建议仅检测那些有直接影响的“怪癖”,而且最好在脚本一开始就执行此类检测。

三、用户代理检测

用户代理检测:通过检测用户代理字符串来确定实际使用的浏览器。
在HTTP请求时,用户代理字符串作为响应首部发送,该字符串可以通过 navigator.userAgent 属性访问。
服务端,该方法常用且广为接受;客户端,该方法排在能力检测和怪癖检测之后,属于不得已做法。

电子欺骗(spoofing):浏览器通过在自己的用户代理字符串加入一些错误或误导性信息,来达到欺骗服务器的目的。

1. 用户代理字符串历史

HTTP 规范(包括 1.0 和 1.1 版)明确规定:浏览器应该发送简短的用户代理字符串,指明浏览器的名称和版本号。
Mosaic/0.9
现实中的用户代理字符串比较复杂。
Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/534.7 (KHTML, like Gecko) Chrome/7.0.517.44 Safari/534.7 // Chrome 7
移动操作系统 iOS 和 Android 默认的浏览器都基于 WebKit,有额外的 Mobile 记号。
Mozilla/5.0 (iPhone; U; CPU iPhone OS 3_0 like Mac OS X; en-us) AppleWebKit/528.18 (KHTML, like Gecko) Version/4.0 Mobile/7A341 Safari/528.16

2. 用户代理字符串检测技术

一般情况下, 知道呈现引擎和最低限度的版本就可以了。

识别呈现引擎

五大呈现引擎:IE、Gecko、WebKit、KHTML、Opera。
要正确地识别呈现引擎,关键是检测顺序要正确。

  • 第一步检测 Opera:
    原因:它的用户代理字符串有可能完全模仿其他浏览器。
    检测方式:
    必须检测 window.opera 对象(Opera 5+)
    调用 version() 返回一个表示浏览器版本的字符串,确定 Opera 版本号的最佳方式(Opera 7.6+)

  • 第二步检测 WebKit:
    原因:WebKit 的用户代理字符串中包含"Gecko"和 "KHTML"这两个子字符串。
    检测方式:
    WebKit 的用户代理字符串中的"AppleWebKit"是独一无二的,检测最合适

  • 第三步检测 KHTML:
    原因:KHTML 的用户代理字符串中也包含"Gecko"。
    检测方式:
    KHTML 的版本号格式,可以使用类似 WebKit 的正则表达式
    Konqueror 3.1 及更早版本中不包含 KHTML 的版本,使用 Konqueror 的版本来代替

  • 第四步检测 Gecko:
    原因:已经排除了 WebKit 和 KHTML
    检测方式:
    Gecko 版本号在 ‘rv:’ 字符串后面,使用一个比较复杂的正则表达式

  • 第五步检测 IE:
    检测方式:
    IE 的版本号位于字符串"MSIE"后面一个分号前面,使用一个简单的正则表达式

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)) {
  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 = RegExp["$1"];
  engine.ie = parseFloat(engine.ver);
}
识别浏览器

Safari 和 Chrome 浏览器都使用 WebKit 作为呈现引擎,但它们的 JavaScript 引擎却不一样。
提取 Chrome 的版本号时,需要查找字符串 “Chrome/” 并取得该字符串后面的数值。
提取 Safari 的版本号时,需要查找字符串 “Version/” 并取得其后的数值(Safari 3+)。
检测 Firefox 的版本时,查找字符串 “Firefox/” 并提取后面的数值。

识别平台

目前三大主流平台:Windows、Mac、Unix(包括各种 Linux)。
检测平台:navigator.platform
可能的值包括:“Win32”、“Win64”、“MacPPC”、“MacIntel”、“X11”、“Linux i686”

识别 Windows 操作系统

为了检测不同的 Windows 操作系统,必须要使用正则表达式。

识别移动设备

检测 IOS设备,可以检测字符串"iPhone"、“iPod"和"iPad”,iOS 的版本号,需要正则表达式
检测 Android 操作系统,搜索字符串"Android"并取得紧随其后的版本号。

识别游戏系统

Wii 中的浏览器实际上是定制版的 Opera,是专门为 Wii Remote 设计的。- 检测字符串"Wii"
Playstation 的浏览器是自己开发的,没有基于前面提到的任何呈现引擎。- 使用正则表达式

3. 完整的代码

完整的用户代理字符串检测脚本,包括检测呈现引擎、平台、Windows 操作系统、移动设备和游戏系统。
代码太多了,就不展示了。
对这部分有兴趣的,自行查阅红宝书。

四. 总结

选择客户端检测方法:
优先使用能力检测
怪癖检测是确定应该如何处理代码的第二选择;
用户代理检测是客户端检测的最后一种方案。


上一篇:19-JavaScript高级程序设计-location对象
下一篇:21-JavaScript高级程序设计-DOM节点(上)

全书整理版:《Javascript高级程序设计》第3版(总结版)


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值