Javascript基础——浏览器检测
浏览器检测学习要点
由于每个浏览器都具有自己独到的扩展,所以在开发阶段来判断浏览器是一个非常重要的步骤。虽然浏览器开发商在公共接口方面投入了很多精力, 努力的去支持最常用的公共功能; 但在现实中, 浏览器之间的差异, 以及不同浏览器的“ 怪癖”却是非常多的, 因此客户端检测除了是一种补救措施,更是一种行之有效的开发策略。
navigator对象
navigator对象最早由 NetscapeNavigator2.0引入的 navigator对象,现在已经成为识别客户端浏览器的事实标准。 与之前的 BOM对象一样, 每个浏览器中 的 navigator对象也都有一套自己的属性。
navigator对象的属性或方法:
1、浏览器及版本号
不同的浏览器支持的功能、 属性和方法各有不同。 比如 IE 和 Firefox 显示的页面可能就会有所略微不同。
2、浏览器嗅探器
浏览器嗅探器是一段程序,有了它,浏览器检测就变得简单了。我们这里提供了一个
browserdetect.js 文件,用于判断浏览器的名称、版本号及操作系统。完整代码如下:
var BrowserDetect = {
init: function () {
this.browser = this.searchString(this.dataBrowser) || "An unknown browser";
this.version = this.searchVersion(navigator.userAgent)
|| this.searchVersion(navigator.appVersion)
|| "an unknown version";
this.OS = this.searchString(this.dataOS) || "an unknown OS";
},
searchString: function (data) {
for (var i=0;i<data.length;i++) {
var dataString = data[i].string;
var dataProp = data[i].prop;
this.versionSearchString = data[i].versionSearch || data[i].identity;
if (dataString) {
if (dataString.indexOf(data[i].subString) != -1)
return data[i].identity;
}
else if (dataProp)
return data[i].identity;
}
},
searchVersion: function (dataString) {
var index = dataString.indexOf(this.versionSearchString);
if (index == -1) return;
return parseFloat(dataString.substring(index+this.versionSearchString.length+1));
},
dataBrowser: [
{
string: navigator.userAgent,
subString: "Chrome",
identity: "Chrome"
},
{ string: navigator.userAgent,
subString: "OmniWeb",
versionSearch: "OmniWeb/",
identity: "OmniWeb"
},
{
string: navigator.vendor,
subString: "Apple",
identity: "Safari",
versionSearch: "Version"
},
{
prop: window.opera,
identity: "Opera"
},
{
string: navigator.vendor,
subString: "iCab",
identity: "iCab"
},
{
string: navigator.vendor,
subString: "KDE",
identity: "Konqueror"
},
{
string: navigator.userAgent,
subString: "Firefox",
identity: "Firefox"
},
{
string: navigator.vendor,
subString: "Camino",
identity: "Camino"
},
{ // for newer Netscapes (6+)
string: navigator.userAgent,
subString: "Netscape",
identity: "Netscape"
},
{
string: navigator.userAgent,
subString: "MSIE",
identity: "Internet Explorer",
versionSearch: "MSIE"
},
{
string: navigator.userAgent,
subString: "Gecko",
identity: "Mozilla",
versionSearch: "rv"
},
{ // for older Netscapes (4-)
string: navigator.userAgent,
subString: "Mozilla",
identity: "Netscape",
versionSearch: "Mozilla"
}
],
dataOS : [
{
string: navigator.platform,
subString: "Win",
identity: "Windows"
},
{
string: navigator.platform,
subString: "Mac",
identity: "Mac"
},
{
string: navigator.userAgent,
subString: "iPhone",
identity: "iPhone/iPod"
},
{
string: navigator.platform,
subString: "Linux",
identity: "Linux"
}
]
};
BrowserDetect.init();
3、检测插件
插件是一类特殊的程序。 他可以扩展浏览器的功能, 通过下载安装完成。 比如, 在线音乐、视频动画等等插件。
navigator对象的 plugins属性,这个一个数组。存储在浏览器已安装插件的完整列表。
//列出所有的插件名
for (var i = 0; i < navigator.plugins.length; i++) {
document.write(navigator.plugins[i].name + '<br />');
}
检测非IE插件是否存在:
function hasPlugin(name) {
var name = name.toLowerCase();
for (var i = 0; i < navigator.plugins.length; i++) {
if (navigator.plugins[i].name.toLowerCase().indexOf(name) > -1) {
return true;
}
}
return false;
}
alert(hasPlugin('Flash')); //检测 Flash是否存在
alert(hasPlugin('java')) //检测 Java是否存在
4、ActiveX
IE浏览器没有插件,但是提供了ActiveX控件,ActiveX控件是一种在Web页面中嵌入对象或者组建的方法。
由于在JS中,我们无法将所有已经安装的ActiveX控件遍历出来,但是我们还是可以去验证是否安装了控件。
检测IE中的控件:
function hasIEPlugin(name) {
try {
new ActiveXObject(name);
return true;
} catch (e) {
return false;
}
}
alert(hasIEPlugin('ShockwaveFlash.ShockwaveFlash'));
PS: ShockwaveFlash.ShockwaveFlash是IE中代表FLASH的标识符,你需要检查哪种控件,必须先获取它的标识符。
5、MIME类型
MIME是指多用途因特网邮件扩展。它是通过因特网发送邮件消息的标准格式。现在也被用于在因特网中交换各种类型的文件。
PS: mimeType[]数组在IE中不产生输出。
mimeType对象的属性:
//遍历非IE下所有MIME类型信息
for (var i = 0; i < navigator.mimeTypes.length; i++) {
if (navigator.mimeTypes[i].enabledPlugin != null) {
document.write('<dl>');
document.write('<dd>类型名称: ' + navigator.mimeTypes[i].type + '</dd>');
document.write('<dd>类型引用: ' + navigator.mimeTypes[i].enabledPlugin.name +
'</dd>');
document.write('<dd>类型描述: ' + navigator.mimeTypes[i].description + '</dd>');
document.write('<dd>类型后缀: ' + navigator.mimeTypes[i].suffixes + '</dd>');
document.write('</dl>')
}
}
客户端检测
客户端检测一共分为三种, 分别为: 能力检测、 怪癖检测和用户代理检测, 通过这三种检测方案,我们可以充分的了解当前浏览器所处系统、所支持的语法、所具有的特殊性能。
1、能力监测
能力检测又称作为特性检测, 检测的目标不是识别特定的浏览器, 而是识别浏览器的能力。 能力检测不必估计特定的浏览器, 只需要确定当前的浏览器是否支持特定的能力, 就可以给出可行的解决方案。
//BOM章节的一段程序
var width = window.innerWidth; //如果是非 IE浏览器
if (typeof width != 'number') { //如果是 IE,就使用 document
if (document.compatMode == 'CSS1Compat') {
width = document.documentElement.clientWidth;
} else {
width = document.body.clientWidth; //非标准模式使用 body
}
}
PS:上面其实有两块地方使用了能力检测,第一个就是是否支持 innerWidth的检测,
第二个就是是否是标准模式的检测,这两个都是能力检测。
2、怪癖检测(bug检测)
与能力检测类似, 怪癖检测的目标是识别浏览器的特殊行为。但与能力检测确认浏览器支持什么能力不同,怪癖检测是想要知道浏览器存在什么缺陷(bug)。bug一般属于个别浏览器独有,在大多数新版本的浏览器被修复。在后续的开发过程中,
如果遇到浏览器 bug我们再详细探讨。
var box = {
toString: function() {} //创建一个 toString(),和原型中重名了
};
for (var o in box) {
alert(o); //IE浏览器的一个 bug,不识别了
}
3、用户代理检测
用户代理检测通过检测用户代理字符串来确定实际使用的浏览器。在每一次 HTTP请求过程中,用户代理字符串是作为响应首部发送的,而且该字符串可以通过 JavaScript的navigator.userAgent属性访问。用户代理代理检测, 主要通过 navigator.userAgent来获取用户代理字符串的, 通过这组字符串,我们来获取当前浏览器的版本号、浏览器名称、系统名称。
PS:在服务器端,通过检测用户代理字符串确定用户使用的浏览器是一种比较广为接受的做法。 但在客户端, 这种测试被当作是一种万不得已的做法, 且饱受争议, 其优先级排在能力检测或怪癖检测之后。饱受争议的原因,是因为它具有一定的欺骗性。
document.write(navigator.userAgent); //得到用户代理字符串
只要仔细的阅读这些字符串, 我们可以发现, 这些字符串包含了浏览器的名称、 版本和所宿主的操作系统。
每个浏览器有它自己的呈现引擎: 所谓呈现引擎, 就是用来排版网页和解释浏览器的引擎。通过代理字符串发现,我们归纳出浏览器对应的引擎:
IE--Trident, IE8体现出来了,之前的未体现
Firefox--Gecko,
Opera--Presto, 旧版本根本无法体现呈现引擎
Chrome--WebKit WebKit是KHTML呈现引擎的一个分支,后独立开来
Safari--WebKit
Konqueror—KHTML
由上面的情况, 我们需要检测呈现引擎可以分为五大类: IE、 Gecko、 WebKit、 KHTML和Opera。
var client = function() { //创建一个对象
var engine = { //呈现引擎
ie: false,
gecko: false,
webkit: false,
khtml: false,
opera: false,
ver: 0 //具体的版本号
};
return {
engine: engine //返回呈现引擎对象
};
}(); //自我执行
alert(client.engine.ie); //获取ie
以上的代码实现了五大引擎的初始化工作,分别给予true的初值,并且设置版本号为0。