JavaScript 判断浏览器类型及版本


Posted in Javascript onFebruary 21, 2009

几天前,浏览器家族有刚诞生了一位小王子,就是Google推出的Chrome浏览器。由于Chrome出生名门,尽管他还是个小家伙,没有人敢小看他。以后,咱们常说浏览器的“四大才子”就得改称为“五朵金花”了。
在网站前端开发中,浏览器兼容性问题本已让我们手忙脚乱,Chrome的出世不知道又要给我们添多少乱子。浏览器兼容性是前端开发框架要解决的第一个问题,要解决兼容性问题就得首先准确判断出浏览器的类型及其版本。
JavaScript是前端开发的主要语言,我们可以通过编写JavaScript程序来判断浏览器的类型及版本。JavaScript判断浏览器类型一般有两种办法,一种是根据各种浏览器独有的属性来分辨,另一种是通过分析浏览器的userAgent属性来判断的。在许多情况下,值判断出浏览器类型之后,还需判断浏览器版本才能处理兼容性问题,而判断浏览器的版本一般只能通过分析浏览器的userAgent才能知道。
我们先来分析一下各种浏览器的特征及其userAgent。
IE
只有IE支持创建ActiveX控件,因此她有一个其他浏览器没有的东西,就是ActiveXObject函数。只要判断window对象存在 ActiveXObject函数,就可以明确判断出当前浏览器是IE。而IE各个版本典型的userAgent如下:

Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0) 

Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.2) 

Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1) 

Mozilla/4.0 (compatible; MSIE 5.0; Windows NT)

其中,版本号是MSIE之后的数字。
Firefox
Firefox中的DOM元素都有一个getBoxObjectFor函数,用来获取该DOM元素的位置和大小(IE对应的中是 getBoundingClientRect函数)。这是Firefox独有的,判断它即可知道是当前浏览器是Firefox。Firefox几个版本的 userAgent大致如下:
Mozilla/5.0 (Windows; U; Windows NT 5.2) Gecko/2008070208 Firefox/3.0.1 

Mozilla/5.0 (Windows; U; Windows NT 5.1) Gecko/20070309 Firefox/2.0.0.3 

Mozilla/5.0 (Windows; U; Windows NT 5.1) Gecko/20070803 Firefox/1.5.0.12

其中,版本号是Firefox之后的数字。
Opera
Opera提供了专门的浏览器标志,就是window.opera属性。Opera典型的userAgent如下:
Opera/9.27 (Windows NT 5.2; U; zh-cn) 

Opera/8.0 (Macintosh; PPC Mac OS X; U; en) 

Mozilla/5.0 (Macintosh; PPC Mac OS X; U; en) Opera 8.0

其中,版本号是靠近Opera的数字。
Safari
Safari浏览器中有一个其他浏览器没有的openDatabase函数,可做为判断Safari的标志。Safari典型的userAgent如下:
Mozilla/5.0 (Windows; U; Windows NT 5.2) AppleWebKit/525.13 (KHTML, like Gecko) Version/3.1 Safari/525.13 

Mozilla/5.0 (iPhone; U; CPU like Mac OS X) AppleWebKit/420.1 (KHTML, like Gecko) Version/3.0 Mobile/4A93 Safari/419.3

其版本号是Version之后的数字。
Chrome
Chrome有一个MessageEvent函数,但Firefox也有。不过,好在Chrome并没有Firefox的getBoxObjectFor 函数,根据这个条件还是可以准确判断出Chrome浏览器的。目前,Chrome的userAgent是:
Mozilla/5.0 (Windows; U; Windows NT 5.2) AppleWebKit/525.13 (KHTML, like Gecko) Chrome/0.2.149.27 Safari/525.13
其中,版本号在Chrome只后的数字。
有趣的是,Chrome的userAgent还包含了Safari的特征,也许这就是Chrome可以运行所有Apple浏览器应用的基础吧。
只要了解了以上信息,我们就可以根基这些特征来判断浏览器类型及其版本了。我们会将判断的结果保存在Sys名字空间中,成为前端框架的基本标志信息,供今后的程序来读取。如果判断出谋种浏览器,Sys名字空间将有一个该浏览器名称的属性,其值为该浏览器的版本号。例如,如果判断出IE 7.0,则Sys.ie的值为7.0;如果判断出Firefox 3.0,则Sys.firefox的值为3.0。下面是判断浏览器的代码:
<script type="text/javascript"> 
var Sys = {}; 
var ua = navigator.userAgent.toLowerCase(); 
if (window.ActiveXObject) 
Sys.ie = ua.match(/msie ([\d.]+)/)[1] 
else if (document.getBoxObjectFor) 
Sys.firefox = ua.match(/firefox\/([\d.]+)/)[1] 
else if (window.MessageEvent && !document.getBoxObjectFor) 
Sys.chrome = ua.match(/chrome\/([\d.]+)/)[1] 
else if (window.opera) 
Sys.opera = ua.match(/opera.([\d.]+)/)[1] 
else if (window.openDatabase) 
Sys.safari = ua.match(/version\/([\d.]+)/)[1]; 
//以下进行测试 
if(Sys.ie) document.write('IE: '+Sys.ie); 
if(Sys.firefox) document.write('Firefox: '+Sys.firefox); 
if(Sys.chrome) document.write('Chrome: '+Sys.chrome); 
if(Sys.opera) document.write('Opera: '+Sys.opera); 
if(Sys.safari) document.write('Safari: '+Sys.safari); 
</script>

我们把对IE的判断放在第一,因为IE的用户最多,其次是判断Firefox。按使用者多少的顺序来判断浏览器类型,可以提高判断效率,少做无用功。之所以将Chrome放在第三判断,是因为我们预测Chrome很快会成为市场占有率第三的浏览器。其中,在分析浏览器版本时,用到了正则表达式来析取其中的版本信息。
如果你的JavaScript玩得很高,你还可以将前面的判断代码写成这样:

<script type="text/javascript"> 
var Sys = {}; 
var ua = navigator.userAgent.toLowerCase(); 
window.ActiveXObject ? Sys.ie = ua.match(/msie ([\d.]+)/)[1] : 
document.getBoxObjectFor ? Sys.firefox = ua.match(/firefox\/([\d.]+)/)[1] : 
window.MessageEvent && !document.getBoxObjectFor ? Sys.chrome = ua.match(/chrome\/([\d.]+)/)[1] : 
window.opera ? Sys.opera = ua.match(/opera.([\d.]+)/)[1] : 
window.openDatabase ? Sys.safari = ua.match(/version\/([\d.]+)/)[1] : 0; 
//以下进行测试 
if(Sys.ie) document.write('IE: '+Sys.ie); 
if(Sys.firefox) document.write('Firefox: '+Sys.firefox); 
if(Sys.chrome) document.write('Chrome: '+Sys.chrome); 
if(Sys.opera) document.write('Opera: '+Sys.opera); 
if(Sys.safari) document.write('Safari: '+Sys.safari); 
</script>

这样可以使JavaScript代码更精简些。当然,可读性稍差一些,就看你是重视效率还是重视可维护性了。
使用不同特征来判断浏览器的方法,虽然在速度上比用正则表达式分析userAgent要来的快,不过这些特征可能会随浏览器版本而变化。比如,一种浏览器本来独有的特性取得了市场上的成功,其他浏览器也就可能跟着加入该特性,从而使该浏览器的独有特征消失,导致我们的判断失败。因此,相对比较保险的做法是通过解析userAgent中的特征来判断浏览器类型。何况,反正判断版本信息也需要解析浏览器的userAgent的。
通过分析各类浏览器的userAgent信息,不难得出分辨各类浏览器及其版本的正则表达式。而且,对浏览器类型的判断和版本的判断完全可以合为一体地进行。于是,我们可以写出下面的代码:

<script type="text/javascript"> 
var Sys = {}; 
var ua = navigator.userAgent.toLowerCase(); 
var s; 
(s = ua.match(/msie ([\d.]+)/)) ? Sys.ie = s[1] : 
(s = ua.match(/firefox\/([\d.]+)/)) ? Sys.firefox = s[1] : 
(s = ua.match(/chrome\/([\d.]+)/)) ? Sys.chrome = s[1] : 
(s = ua.match(/opera.([\d.]+)/)) ? Sys.opera = s[1] : 
(s = ua.match(/version\/([\d.]+).*safari/)) ? Sys.safari = s[1] : 0; 
//以下进行测试 
if (Sys.ie) document.write('IE: ' + Sys.ie); 
if (Sys.firefox) document.write('Firefox: ' + Sys.firefox); 
if (Sys.chrome) document.write('Chrome: ' + Sys.chrome); 
if (Sys.opera) document.write('Opera: ' + Sys.opera); 
if (Sys.safari) document.write('Safari: ' + Sys.safari); 
</script>

其中,采用了“... ? ... : ...”这样的判断表达式来精简代码。判断条件是一条赋值语句,既完成正则表达式的匹配及结果复制,又直接作为条件判断。而随后的版本信息只需从前面的匹配结果中提取即可,这是非常高效的代码。
以上的代码都是为了打造前端框架所做的预研,并在五大浏览器上测试通过。今后,判断某种浏览器只需用if(Sys.ie)或 if(Sys.firefox)等形式,而判断浏览器版本只需用if(Sys.ie == '8.0')或if(Sys.firefox == '3.0')等形式,表达起来还是非常优雅的。
前端框架项目已经启动,一切就看过程和结果了...
原创:李战(leadzen) 阿里软件 2008-9-6 杭州

为了让大家更尽兴三水点靠木小编特多整理几个:

<script language="JavaScript"> 
function getOs() 
{ 
  var OsObject = ""; 
  if(navigator.userAgent.indexOf("MSIE")>0) { 
    return "MSIE"; //ie浏览器
  } 
  if(isChrome=navigator.userAgent.indexOf("Chrome")>0){ 
    return "chrome"; //Chrome浏览器
  } 
  if(isFirefox=navigator.userAgent.indexOf("Firefox")>0){ 
    return "Firefox"; //Firefox浏览器
  } 
  if(isOpera=navigator.userAgent.indexOf("Opera")>0) { 
    return "Opera"; //Opera浏览器
  } 
  if(isSafari=navigator.userAgent.indexOf("Safari")>0) { 
    return "Safari"; //Safari浏览器
  }  
  if(isCamino=navigator.userAgent.indexOf("Camino")>0){ 
    return "Camino"; //Camino浏览器
//……增加一些其它代码……
  } 
  if(isMozilla=navigator.userAgent.indexOf("Gecko/")>0){ 
    return "Gecko"; 
  } 
} 
alert(navigator.userAgent);
 alert("您的浏览器类型为:"+getOs()); 
</script>

比较全的判断代码

<script type="text/javascript"> 
document.write('浏览器判?e:');
var OsObject=navigator.userAgent;
// 包含「Opera」文字列 
if(OsObject.indexOf("Opera") != -1) 
{ 
   document.write('您的浏览器是Opera吧?'); 
} 
// 包含「MSIE」文字列 
else if(OsObject.indexOf("MSIE") != -1) 
{ 
   document.write('您的浏览器是Internet Explorer吧?'); 
} 
// 包含「chrome」文字列 ,不过360浏览器也照抄chrome的UA

else if(OsObject.indexOf("Chrome") != -1) 
{ 
  document.write('您的浏览器是chrome或360浏览器吧?'); 
}
// 包含「UCBrowser」文字列 
else if(OsObject.indexOf("UCBrowser") != -1) 
{ 
  document.write('您的浏览器是UCBrowser吧?'); 
}
// 包含「BIDUBrowser」文字列 
else if(OsObject.indexOf("BIDUBrowser") != -1) 
{ 
  document.write('您的浏览器是百度浏览器吧?'); 
}
// 包含「Firefox」文字列 
else if(OsObject.indexOf("Firefox") != -1) 
{ 
  document.write('您的浏览器是Firefox吧?'); 
}
// 包含「Netscape」文字列 
else if(OsObject.indexOf("Netscape") != -1)
{ 
  document.write('您的浏览器是Netscape吧?'); 
} 
// 包含「Safari」文字列 
else if(OsObject.indexOf("Safari") != -1) 
{ 
   document.write('您的浏览器是Safari 吧?'); 
} 
else{ 
  document.write('无法识别的浏览器。'); 
} 
</script>
Javascript 相关文章推荐
javascript学习笔记(一)基础知识
Sep 30 Javascript
jQuery封装的tab选项卡插件分享
Jun 16 Javascript
jQuery的Scrollify插件实现滑动到页面下一节点
Jul 05 Javascript
javascript创建cookie、读取cookie
Mar 31 Javascript
举例讲解jQuery中可见性过滤选择器的使用
Apr 18 Javascript
Laydate时间组件在火狐浏览器下有多时间输入框时只能给第一个输入框赋值的解决方法
Aug 18 Javascript
基于jQuery实现的幻灯图片切换
Dec 02 Javascript
使用Angular缓存父页面数据的方法
Jan 03 Javascript
angularJS之$http:与服务器交互示例
Mar 17 Javascript
vue axios 给生产环境和发布环境配置不同的接口地址(推荐)
May 08 Javascript
微信小程序学习笔记之目录结构、基本配置图文详解
Mar 28 Javascript
微信小程序用户登录和登录态维护的实现
Dec 10 Javascript
JavaScript 调试器简介
Feb 21 #Javascript
用jQuery简化JavaScript开发分析
Feb 19 #Javascript
Javascript 同时提交多个Web表单的方法
Feb 19 #Javascript
javascript function、指针及内置对象
Feb 19 #Javascript
csdn 批量接受好友邀请
Feb 19 #Javascript
判断多个元素(RADIO,CHECKBOX等)是否被选择的原理说明
Feb 18 #Javascript
JAVASCRIPT IE 与 FF中兼容问题小结
Feb 18 #Javascript
You might like
PHP使用range协议实现输出文件断点续传代码实例
2014/07/04 PHP
ThinkPHP表单自动验证实例
2014/10/13 PHP
PHP生成不重复标识符的方法
2014/11/21 PHP
php获得文件大小和文件创建时间的方法
2015/03/13 PHP
如何通过Linux命令行使用和运行PHP脚本
2015/07/29 PHP
php封装的表单验证类完整实例
2016/10/19 PHP
PHP设计模式之装饰器模式实例详解
2018/02/07 PHP
window.onload 加载完毕的问题及解决方案(上)
2009/07/09 Javascript
IE iframe的onload方法分析小结
2010/01/07 Javascript
js 兼容多浏览器的回车和鼠标焦点事件代码(IE6/7/8,firefox,chrome)
2010/04/14 Javascript
javascript smipleChart 简单图标类
2011/01/12 Javascript
来自国外的30个基于jquery的Web下拉菜单
2012/06/22 Javascript
关于JavaScript中string 的replace
2013/04/12 Javascript
JQGrid的用法解析(列编辑,添加行,删除行)
2013/11/08 Javascript
jQuery使用post方法提交数据实例
2015/03/25 Javascript
JS实现常见的TAB、弹出层效果(TAB标签,斑马线,遮罩层等)
2015/10/08 Javascript
AngularJS使用ng-inlude指令加载页面失败的原因与解决方法
2017/01/19 Javascript
元素全屏的设置与监听实例
2017/11/28 Javascript
基于vue 开发中出现警告问题去除方法
2018/01/25 Javascript
jQuery代码优化方法总结
2018/01/29 jQuery
如何在selenium中使用js实现定位
2020/08/18 Javascript
[19:59]2014DOTA2国际邀请赛 IG战队纪录片
2014/08/07 DOTA
[54:33]2018DOTA2亚洲邀请赛小组赛 A组加赛 Liquid vs Optic
2018/04/03 DOTA
[48:31]DOTA2-DPC中国联赛 正赛 Dynasty vs XG BO3 第一场 2月2日
2021/03/11 DOTA
python的几种开发工具介绍
2007/03/07 Python
Python ORM框架SQLAlchemy学习笔记之映射类使用实例和Session会话介绍
2014/06/10 Python
Python单例模式实例分析
2015/01/14 Python
常见python正则用法的简单实例
2016/06/21 Python
关于python多重赋值的小问题
2019/04/17 Python
CSS3中Color的一些特性介绍
2012/05/27 HTML / CSS
个人作风剖析材料
2014/02/02 职场文书
安全生产实施方案
2014/02/23 职场文书
党政领导班子民主生活会整改措施
2014/09/18 职场文书
入党介绍人考察意见
2015/06/01 职场文书
2016年春季运动会广播稿
2015/08/19 职场文书
JS数组方法some、every和find的使用详情
2021/10/05 Javascript