风舞残阳 2008-4-1 11:20
用JavaScript检测浏览器的相关特性
一、检测[wiki]浏览器[/wiki]的名称
问题:
不同的浏览器对javascript的[wiki]标准[/wiki]支持也有不同,有时希望脚本能够在不同的浏览器上都能运行良好,这时需要对浏览器进行检测,确定其名称,以针对不同的浏览器编写相应的脚本。
解决方案:
使用navigator[wiki]对象[/wiki]的appName属性。
比如,要检测浏览器是否为IE,可以这么做:
varisIE=(navigator.appName=="MicrosoftInternetExplorer");
document.write("isIE?"+isIE);
对于FireFox,navigator对象的appName属性值为"Netscape";Opera9.02的appName属性值为"Opera"(其更早版本可能不同);
二、检测浏览器的版本号:
问题:
随着浏览器的版本的更迭,浏览器所支持的脚本特性也在变化,有时候就需要针对不同的版本编写相应的脚本,那么如何获得浏览器的版本号?
解决方案:
通过解析navigator对象的userAgent属性来获得浏览器的完整版本号。
IE将自己标识为MSIE,后面带一个空格,版本号以及分号。所以我们只要取空格和分号之间的部分即可。如Windows[wiki]XP[/wiki]SP2所带的IE的userAgent属性值为"Mozilla/4.0(compatible;MSIE6.0;WindowsNT5.1;SV1;.NE[wiki]TCL[/wiki]R1.1.4322;.NETCLR2.0.50727)",可以看到其版本为6.0。可以用如下的函数来获取IE浏览器的版本号:
functiongetIEVersonNumber()
{
varua=navigator.userAgent;
varmsieOffset=ua.indexOf("MSIE");
if(msieOffset%26lt;0)
{
return0;
}
returnparseFloat(ua.substring(msieOffset+5,ua.indexOf(";",msieOffset)));
}
假设我们要为IE5及以上版本编写脚本,可以这么写:
varisIE5Min=(getIEVersonNumber()%26gt;=5);
if(isIE5Min)
{
//performstatementsforIE5orlater
}
对于FireFox和Opera等浏览器,也可以用navigator.userAgent属性来获取其版本号,只不过其形式与IE有所不同,如FireFox:
Mozilla/5.0(Windows;U;WindowsNT5.1;en-US;rv:1.8.0.7)Gecko/20060909Firefox/1.5.0.7
Opera:Opera/9.02(WindowsNT5.1;U;en)根据这些形式,我们不难获得其版本号。但这些浏览器的其它版本没有[wiki]测试[/wiki]过,其具体值不明确,如果要使用这种方法检测,请自行验证。
下面讨论下,上面的那段为IE5及以上版本浏览器编写的脚本,使用这种写法要注意:要用%26gt;=而不是==,一般情况下,我们可以假定浏览器是向后兼容的,所以使用==显然不能适应新版本;另一方面,我们上面的假定也仅仅是假定,不能确保是这样,如果浏览器的某些对象或属性不能向后兼容,我们的代码也会产生问题,所以建议,少用浏览器版本的比较,更多情况下,应检测是要用的对象或属性是否得到支持。
三、检测客户端的操作[wiki]系统[/wiki][wiki]类[/wiki]型
根据上面的讨论可以看到,navigator.userAgent属性通常含有[wiki]操作系统[/wiki]的基本[wiki]信息[/wiki],但很不幸,没有统一的规则去根据userAgent获取准确的操作系统信息,因为这些值与浏览器的种类、浏览器的版本甚至浏览器的[wiki]OEM[/wiki]版本都有关系。
通常我们能做的是,检测一些更为通用的信息,比如操作系统是Windows还是Mac,而不是去看是Windows98还是WindowsXP。其规则是所有的Windows版本都会含有"Win",所有的Macintosh版本都含有"Mac",所有的[wiki]Unix[/wiki]则含有"X11",而在Linux下则同时包含"X11"和"Linux"。如:
varisWin=(navigator.userAgent.indexOf("Win")!=-1);
varisMac=(navigator.userAgent.indexOf("Mac")!=-1);
varisUnix=(navigator.userAgent.indexOf("X11")!=-1);
通常用在为不同的操作系统设置不同的字体或位置等样式。
四、检测浏览器对特定对象的支持
问题:
如果需要编写对多种浏览器或浏览器的多个版本都能适用的脚本,就要进行检测一下,浏览器是否支持某个对象。当然这种检测主要是针对那些潜在的不兼容对象的语句。
解决方案:
早期的浏览器对于img[wiki]元素[/wiki]的支持差别很大,所以要在脚本中操作img元素,需要检测浏览器是否支持。这时我们不需要对所有可能的浏览器一一检测,只需在必要的地方用下面的方式检测:
functionrollover(imgName,imgSrc)
{
//如果支持images对象
if(document.images)
{
//statementsgohere
}
}
这种方法能够生效是基于一个事实:如果document.images对象不存在,那么if求值的结果为false。
使用这种方法,使得对对象的检测变得简单易行,但是我们要注意,对于那些不支持该对象的浏览器要如何较好得处理。看下面的代码:
functiongetImgAreas()
{
varresult=0;
for(vari=0;i%26lt;document.images.length;i++)
{
result+=(document.images[i].width*document.images[i].height);
}
returnresult;
}
functionreportImageArea()
{
document.form1.imgData.value=getImgAreas();
}
这里没用对象支持的检测。如果浏览器支持document.images,这两个函数运行正常;否则就会抛出异常。下面是改进的脚本:
functiongetImgAreas()
{
varresult;
//检测浏览器是否支持对象
if(document.images)
{
result=0;
for(vari=0;i%26lt;document.images.length;i++)
{
result+=(document.images[i].width*document.images[i].height);
}
}
//返回值为一个数字或null
returnresult;
}
functionreportImageArea()
{
//现在可以判断返回值
varimgArea=getImgAreas();
varoutput;
if(imgArea==null)
{
//对于不支持images对象的浏览器也要给出相应信息
output="Unknown";
}else{
output=imgArea;
}
document.reportForm.imgData.value=output;
}
这样,不管浏览器是否支持该对象,都能给用户比较合理的信息,而不会跳出突兀的错误信息。
五、检测浏览器对特定属性和方法的支持
问题:
检测一个对象是否含有某个特定的属性或方法。
解决方案:
大多数情况下,可以用类似于下面的代码来判断:
if(objectTest%26%26objectPropertyTest)
{
//OKtoworkwithproperty
}
先检测对象是否存在,然后再检测对象的属性是否存在。如果对象确实不存在,该方法有效;如果属性存在,但其值为null,0,false,if语句求值的结果也将是false!所以这种方法并不安全,最好的方法是这样:
if(objectReference%26%26typeof(objectReference.propertyName)!="undefined")
{
//OKtoworkwithproperty
}
对于方法的检测也可用类似的方法:
functionmyFunction()
{
if(document.getElementById)
{
//这里可以使用getElementById方法
}
}