Internet上充斥着各种操作系统和各种版本的浏览器,每种浏览器都有自己的BOM和独有的特性。因此,保证页面在所有浏览器上正常运行是非常重要的,或者至少可以正常退出,例如显示一个消息建议用户升级浏览器。
有两种方法可以测试浏览器是否可以执行代码:特性检测和浏览器嗅探。它们的最终目标类似,测试给定的浏览器是否执行代码,但它们用于不同的目的。
特性检测
并非所有的浏览器都支持相同的特性,这里的特性是指对于JavaScript开发人员而言可以在代码中访问和使用的特性。特性检测是指检测浏览器是否支持某个给定特性的过程,该方法是浏览器检测的首选方法。使用该方法时,需要做少许的维护工作,所有实现(或不实现)特定特性的浏览器都使用这种方法来检测代码的执行。
特性检测的模式很简单:首先检查特性是否存在,如果存在,就使用该特性。因此,使用一个if语句即可实现,如下所示:
if(navigator.geolocation){
//user geolocation
}
这段代码将navigator.geolocation用作if语句的条件。在不支持geolocation的浏览器中,navigator.geolocation为undefined,因此值为falsey。
尽管if语句的条件值应被设为true或false,但JavaScript可以将任何值当作true或false。我们称这些值为truthy和falsey。它们并不是真正的布尔值,但用在条件语句中时,其结果就为true或false了。
以下值为falsey:
- 0
- ”” (一个空字符串)
- null
- undefined
- [ ] (一个空数组)
- false
除了上面的值,其他值都为truthy。 -
上面的这种方式令人困惑,也给代码增加了歧义性。现在应尽量避免使用truthy/falsey语句,而是选择使用typeof运算符,如下所示:
if(typeof navigator.geolocation!="undefined"){ //use geolocation }
typeof运算符返回一个说明值或对象类型的字符串。在支持geolocation的浏览器中,类型为”object”,而在不支持geolocation其他浏览器中,类型则为”undefined”。
对于任何对象或值都可以使用typeof运算符。如下表给出了typeof可能返回的值:
语句 结果 typeof() 1 数字number typeof() “hello” 字符串string typeof() true 布尔值boolean typeof() [](或 任何数组) 对象object typeof() {}(或 任何对象) 对象object typeof() undefined 未定义undefined typeof() null 对象object ==
document.write(typeof 1+"<br>"); document.write(typeof "hello"+"<br>"); document.write(typeof true+"<br>"); document.write(typeof [1,2]+"<br>"); document.write(typeof undefined+"<br>"); document.write(typeof null+"<br>");
输出结果为:
number
string
boolean
object
undefined
object特性检测方法特别有用,使用该方法可以将支持或不支持特性的浏览器分离开来。浏览器制造商并非都很完美,有时他们发布的浏览器版本具有唯一且古怪的功能。这样,就需要区分单个浏览器,使用特性检测就可以很好地实现这一点。
浏览器嗅探
在大多数情况下,首选使用特性检测方法。浏览器嗅探方法具有许多缺陷,其中之一就是少数浏览器可能宣称自己是某主流浏览器,其实并不是那种浏览器类型。另外一个问题是浏览器嗅探依赖于浏览器的userAgent字符串(user-agent string),该字符串用于标识浏览器,且浏览器制造商可以在不同的版本之间进行大幅度的修改。仅挡针对其有古怪行为的单个浏览器时,才使用浏览器嗅探技术。
navigator对象的appName属性和userAgent属性在标识浏览器方面很有用。appName属性将返回浏览器的模型,如对IE返回Microsoft Internet Explorer,对Firefox,Chrome和Safari返回Netscape。
userAgent属性返回一个包含多段信息的字符串,如浏览器的版本,操作系统和浏览器模型。但是,这个属性的返回值因浏览器而异。例如,浏览器的版本被嵌入在该字符串的不同位置。例如在chrome获取userAgent字符串:
Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.87 Safari/537.36从这个字符串中可以得知使用的是windows10 64位操作系统,Chrome 54.0版本的浏览器。AppleWebKit好像是浏览器内核。后续的操作获取浏览器信息都是根据这个字符串来进行的。
例如:
<script> function getBrowserName(){ var browser=navigator.userAgent; if(browser.indexOf("MSIE")>=0){ return "MSIE"; }else if(browser.indexOf("Firefox")>=0){ return "Firefox"; }else if(browser.indexOf("Chrome")>=0){ return "Chrome"; }else if(browser.indexOf("Safari")>=0){ return "Safari"; }else if(browser.indexOf("Opera")>=0){ return "Opera"; }else{ return "UNKNOWN"; } } function getBrowerVersion() { var ua=navigator.userAgent; var browser=getBrowserName(); var findIndex=ua.indexOf(browser)+browser.length+1; var browserVersion=parseFloat(ua.substring(findIndex,findIndex+3)); return browserVersion; } var browserName=getBrowserName(); var browserVersion=getBrowerVersion(); document.write(browserName+" "+browserVersion); </script>
在Chrome中输出:
Chrome 54
在Opear中输出:
Chrome 55
在Firefox中输出:
Firefox 50通过使用indexOf来搜索检测是否存在某些关键字,如MSIE或者Firefox,通常就可以确定浏览器的名称。只需要观察navifator.userAgent返回的字符串,查找浏览器名称或者唯一标识浏览器的子串。在userAgent字符串中,浏览器的版本信息通常紧跟在浏览器名称之后。有了浏览器的名称和版本信息,就可以利用这些信息过滤用户当前运行的浏览器,从而来检测判断该浏览器是否具有某种特性。
注意:除针对单个浏览器外,不能依赖于浏览器嗅探技术。