ECMAScript虽然是Javascript的核心,但是要在web中使用Javascript,那么BOM才是核心,BOM为我们提供了操作访问浏览器对象的借口,

但是由于BOM没有标准规范,导致存在不一致的问题,所以这里需要客户端检测的方法,突破局限。

  先找出设计通用的的方案,然后再使用特定与浏览器的技术增强该方案。

一、能力检测

  能力检测的目的不是识别浏览器,而是识别浏览器的能力。不必顾及特定的浏览器,只需确定浏览器支持特定的能力。

//浏览器检测的基本模式
if(object.property){
使用object.property
}

  先检测常用的特性,保证了代码最优化。

//上个例子中的代码利用类型转换来确定某个对象是否存在,但这不能保证该成员是不是想要的。
这里更可靠的能力检测
function betterCheck(property){
return (typeof object.property == "function");
}

二、怪癖检测

  怪癖检测的目标是识别浏览器的特殊行为。只是检测浏览器的存在缺陷。

//例如
早期IE8中,如果实例属性与[[enumerable]]为false的某个原型同名,那么这个属性遍不会被for-in循环枚举。可以通过下面的代码来检测这个”怪癖“ var hasEnumQuirk = function () { var o = { toString : function () {} };
for (var pro in o ){
if(pro == "toString")
return false;
} return true;
}

怪癖一般都是浏览器所独有的,通常被归为bug,一般仅检测有直接影响的“怪癖”。

三、用户代理检测

  在浏览器每次发送的http时,都会将userAgent用户代理字符串作为响应首部发送,可以通过navigator.userAgent访问。

  由于经过浏览器大战,现在的浏览器的用户代理都是通过电子欺骗来指定一些误导信息,欺骗服务器。

1、识别呈现引擎

//为了减少全局变量,这里使用增强模块模式。在内部声明了浏览器的呈现引擎,浏览器版本和平台信息
var client = (function () { //呈现引擎
var engine = { ie : 0,
gecko : 0,
webkit : 0,
khtml : 0,
opera : 0, ver : null
}; //浏览器版本
var broswer = { ie : 0,
firefox : 0,
chrome : 0,
safari : 0,
konq : 0,
opera : 0, ver : null
}; //平台信息
var system = { win : false,
mac : false,
x11 : false, //移动设备
iphone : false,
ipod : false,
ipad : false,
ios : false,
andriod : false,
nokia : false,
winMobile : false, //游戏平台 will : false,
ps : false
}; //用户代理检测
var ua = navigator.userAgent;
//opera会将自己完全伪造成其他浏览器所以先检测它
if (window.opera){
engine.opera = broswer.opera = parseInt(engine.ver);
engine.ver = broswer.ver = window.opera.version();
}else if (/AppleWebKit\/(\S+)/.test(ua)){
//webkit引擎的独有特征是AppleWebKit,利用正则表达式来获取版本号
engine.ver = RegExp.$1;
engine.webkit = parseInt(engine.ver); //确认引擎后可以判断浏览器版本,chrome or safari
if (/chrome\/(\S+)/.test(ua)){
broswer.ver = RegExp.$1;
broswer.chrome = parseFloat(broswer.ver);
}else if (/Version\/(\S+)/.test(ua)){
broswer.ver = RegExp.$1;
broswer.safari = parseFloat(broswer.ver);
}else {
var safariVersion = 1; //当判断不出来时,根据引擎版本号来判断浏览器版本
if (engine.webkit < 100){
safariVersion = 1;
} else if (engine.webkit < 312){
safariVersion = 1.2;
} else if(engine.webkit < 412){
safariVersion = 1.3;
} else{
safariVersion = 2;
} broswer.ver = broswer.safari = safariVersion;
}
} else if (/KHTML\/(\S+)/.test(ua) || /Konqueror\/[^;]+/.test(ua)){
engine.ver = broswer.ver = RegExp.$1;
engine.konq = broswer.konq = parseFloat(engine.ver);
} else if (/rv:([^\)]+)\) Gecko\/\d{8}/.test(ua)){
engine.ver = RegExp.$1;
engine.gecko = parseInt(engine.ver); //是否是firefox浏览器
if (/firefox\/(\S+)/i.test(ua)){
broswer.ver = RegExp.$1;
broswer.firefox = parseFloat(broswer.ver);
}
//如果这里没有检测到的firefox岂不是没有浏览器的版本信息了?
} else if (/MSIE ([^;]+)/.test(ua)){
engine.ver = broswer.ver = RegExp.$1;
engine.ie = broswer.ie = parseFloat(engine.ver);
} //检测浏览器,不已经检测过了吗?
broswer.ie = engine.ie;
broswer.opera = engine.opera; //检测平台的开始自动判断平台
var p = navigator.platform;
system.win = p.indexOf("Win") == 0;
system.mac = p.indexOf("Mac") == 0;
system.xll = (p == "X11" || p.indexOf("Linux") == 0); if (system.win){
if (/Win(?:dows )?([^do]{2})\s?(\d+\.\d+)?/.test(ua)){
if (RegExp.$1 == "NT"){
switch(RegExp.$2){
case "5.0":
system.win = "2000";
break; case "5.1":
system.win = "xp";
break; case "6.0":
system.win = "Visita";
break; case "6.1":
system.win = "7";
break; default :
system.win = "NT";
break;
}
} else if (RegExp.$1 == "9x"){
system.win = "ME";
} else {
system.win = RegExp.$1;
}
}
} system.iphone = ua.indexOf("iPhone") > -1;
system.ipod = ua.indexOf("ipod") > -1;
system.ipod = ua.indexOf("ipad") > -1;
system.nokia = ua.indexOf("NokiaN") > -1; //windowMobile
if (system.win == "CE"){
system.winMobilem = system.win;
} else if (system.win == "Ph"){
if(/Windows Phone OS (\d+.\d+)/.test(ua)){
system.win = "Phone";
system.winMobilem = parseFloat(RegExp.$1);
}
} //ios
if (system.mac $$ ua.indexOf("Mobile") > -1){
if (/CPU (?:iPhone ) ?OS (\d+.\d+)/.test(ua)){
system.iso = parseFloat(RegExp.$1.replace("_", "."));
} else {
system.iso = 2;
})
} //检测安卓
if (/Andriod (\d+ \. \d+)/.test(ua)){
system.andriod = parseFloat(RegExp.$1);
} system.will = ua.indexOf("Wii") > -1;
system.ps = /PLAYSTATION/i.test(ua); return {
engine : engine,
broswer : broswer,
system : system
}; })();

浏览器检测只是最后一中选择,只要有可能就应该优先采用能力检测和怪癖检测。适用以下三种情形:

1、不能直接准确的使用能力检测和怪癖检测

2、浏览器在不同平台下不同的能力,需要检测平台。

3、跟踪分析等目的需要知道确切的浏览器。

小结:

客户端检测时有争议的,由于浏览器之间存在差别,通常需要根据不同浏览器,写不同的代码。客户端检测的常用方法:

  1. 能力检测,在编写代码前,先检测浏览器的能力,把注意集中在浏览器的能力存在上。
  2. 怪癖检测,浏览器中的bug的检测。
  3. 用户代理检测,根据用户代理字符串来识别浏览器。

一般,优先考虑能力检测,怪癖检测时第二选择,引文用户代理检测对用户代理字符串的依赖非常强大。

Javascript高级程序设计——客户端检测的更多相关文章

  1. 9. javacript高级程序设计-客户端检测

    1. 客户端检测 1.1 能力检测 在编写代码之前先检测特定浏览器的能力. 1.2 怪癖检测 怪癖实际上是浏览器实现中的bug 1.3 用户代理检测 通过检测用户代理字符串来识别浏览器.用户代理字符串 ...

  2. 《JavaScript高级程序设计(第3版)》阅读总结记录第一章之JavaScript简介

    前言: 为什么会想到把<JavaScript 高级程序设计(第 3 版)>总结记录呢,之前写过一篇博客,研究的轮播效果,后来又去看了<JavaScript 高级程序设计(第3版)&g ...

  3. javascript高级程序设计阅读笔记(一)

    javascript高级程序设计阅读笔记(一) 工作之余开发些web应用作为兴趣,在交互方面需要掌握javascript和css.HTML5等技术,因此读书笔记是必要的. javascript简介 J ...

  4. JavaScript高级程序设计(第三版)学习笔记20、21、23章

    第20章,JSON JSON(JavaScript Object Notation,JavaScript对象表示法),是JavaScript的一个严格的子集. JSON可表示一下三种类型值: 简单值: ...

  5. 读书笔记(04) - 错误监控 - JavaScript高级程序设计

    错误类型 即时运行错误 (代码错误) 资源加载错误 常见的错误 1. 类型转换错误 建议使用全等===操作符 2.数据类型错误 建议加强类型判断 // 数组倒序 function reverseSor ...

  6. JavaScript高级程序设计第三版.CHM【带实例】

    从驱动全球商业.贸易及管理领域不计其数的复杂应用程序的角度来看,说 JavaScript 已经成为当今世界上最流行的编程语言一点儿都不为过. JavaScript 是一种非常松散的面向对象语言,也是 ...

  7. javascript高级程序设计学习笔记

    javascript高级程序设计,当枕头书已经好久了~zz  现在觉得自己在js的开发上遇到了一些瓶颈,归根究底还是基础太薄弱,所以重新刷一遍js高程希望有更新的认识. 一.javascript简介 ...

  8. JavaScript高级程序设计(第4版)pdf 电子书

    JavaScript高级程序设计(第4版)pdf 电子书 免责声明:JavaScript高级程序设计(第4版)pdf 电子书下载 高清收集于网络,请勿商用,仅供个人学习使用,请尊重版权,购买正版书籍. ...

  9. JavaScript高级程序设计(第4版)知识点总结

    介绍 JavaScript高级程序设计 第四版,在第三版的基础上添加了ES6相关的内容.如let.const关键字,Fetch API.工作者线程.模块.Promise 等.适合具有一定编程经验的 W ...

随机推荐

  1. JPA事务总结

    http://www.soso.io/article/65405.html 事务管理是JPA中另一项重要的内容,了解了JPA中的事务管理,能够进一步掌握JPA的使用.事务管理是对一系列操作的管理,它最 ...

  2. django rest framework 入门

    django rest framework 入门1-序列化 Serialization 分类: Python 2013-01-22 22:24 11528人阅读 评论(0) 收藏 举报 djangop ...

  3. shell text process code

     shell 命令处理文本: 1. 批量处理该目录下的文件,ls | while read l ; do echo $l ; done > b.txt 2. 批量处理文件的每一行 , cut - ...

  4. IOS OC 计算器算法(不考虑优先级)

    个人见解:为还在计算器算法方面迷惑的同学一个数据处理解决方案:定义一个可变数组array,一个可变字符串str,使字符通过[array addObject:str];方法添加到可变数组,每当触发运算符 ...

  5. FIFA halts 2026 bids amid scandal 国际足联在丑闻期间停止2026年足球世界杯申请

    FIFA halts 2026 bids amid scandal 国际足联在丑闻期间停止2026年足球世界杯申请 But official insists 2018 Cup will stay in ...

  6. js007-函数表达式

    js007-函数表达式 本章内容 1.函数表达式的特征 2.使用函数实现递归 3.使用闭包定义私有量 定义函数的方式有两种:一:函数声明,二:函数表达式 函数声明: function function ...

  7. PHP_$_SERVER_说明详解

    PHP编程中经常需要用到一些服务器的一些资料,特把$_SERVER的详细参数整理下,方便以后使用. $_SERVER['PHP_SELF'] #当前正在执行 脚本的文件名,与 document roo ...

  8. CURL函数的GET和POST方式的两种写法(实现ajax跨域调用)

    POST请求 function curl_post($url='',$postdata='',$options=array()){ $ch=curl_init($url); curl_setopt($ ...

  9. MyISAM 和InnoDB 区别 转

    MyISAM 和InnoDB 讲解 InnoDB和MyISAM是许多人在使用MySQL时最常用的两个表类型,这两个表类型各有优劣,视具体应用而定.基本的差别为:MyISAM类型不支持事务处理等高级处理 ...

  10. 快捷键_Mac

    苹果Mac系统常用快捷键 Command+Tab 任意情况下切换应用程序 - 向前循环 Shift+Command+Tab 切换应用程序 - 向后循环 Command+L 当前程序是浏览器时,可以直接 ...