jQuery.browser的实现方式
jQuery中的browser对象保存了浏览器的信息。跨浏览器是大多数客户端JS库必须具备的基本特性,判断浏览的类型和版本号并保存在对象中,就是为了针对不同浏览器采取不同的策略。
下面的代码用于展示jQuery.browser的用法:
<script type="text/javascript" src="jquery.js"></script> <script> document.write('$.browser.webkit: ' + $.browser.webkit + '<br />'); document.write('$.browser.opera: ' + $.browser.opera + '<br />'); document.write('$.browser.msie: ' + $.browser.msie + '<br />'); document.write('$.browser.mozilla: ' + $.browser.mozilla + '<br />'); document.write('$.browser.version: ' + $.browser.version); </script>
这段代码在不同浏览器中的显示效果是不同的。
IE中的显示效果如下:
$.browser.webkit: undefined $.browser.opera: undefined $.browser.msie: true $.browser.mozilla: undefined $.browser.version: 8.0
根据$.browser.msie是否为true,就可以判断浏览器是否为IE内核了。而通过$.browser.version可以获得浏览器内核的版本号。其他浏览器可以采用类似的方式进行判断。
jQuery.browser的实现思路如下:
1.通过window.navigator.userAgent获取浏览器的描述字符串
2.使用正则表达式进行匹配,不同浏览器内核对应正则表达式是不同的
3.根据匹配的结果,判断是否为特定浏览器,并提取版本号
4.将结果保存到browser对象中。
首先,让我们测试一下不同浏览器的 window.navigator.userAgent 的输出结果:ua = window.navigator.userAgent; document.write('user agent:<br />' + ua);
GoogleChrome的显示结果:
user agent: Mozilla/5.0 (Windows NT 6.1) AppleWebKit/534.24 (KHTML, like Gecko) Chrome/11.0.696.60 Safari/534.24
我们知道Cheomr的浏览器内核是Webkit,因此其中最重要的是WebKit关键字,但GoogleChrome为了显示其兼容性,也在描述字符串中包含了Mozilla等字样。其他浏览器也有类似的情况。
AppleSafari的显示结果:
user agent: Mozilla/5.0 (Windows; U; Windows NT 6.1; zh-CN) AppleWebKit/533.21.1 (KHTML, like Gecko) Version/5.0.5 Safari/533.21.1
MicrosoftIE8.0的显示结果:
user agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E; Tablet PC 2.0)
MozillaFireFox的显示结果:
user agent: Mozilla/5.0 (Windows; U; Windows NT 6.1; zh-CN; rv:1.9.2.3) Gecko/20100401 Firefox/3.6.3
Opera的显示结果:
user agent: Opera/9.80 (Windows NT 6.1; U; Edition IBIS; zh-cn) Presto/2.8.131 Version/11.10
因为不同浏览器采用的正则表达式是不同的,下面,我们就针对不同的浏览器的情况,对jQuery.browser的实现进行进一步的分析。
GoogleChrome和AppleSafari使用的都是Webkit内核,其描述字符串中也都包含了"Webkit",因此用于检测的正则表达式中需要包含"Webkit"。
另外,版本号是紧跟着"Webkit"关键字的,中间用"/"分隔。因此,我们可以用下面的代码判断浏览器是否为Webkit内核,并提取版本号:
ua = window.navigator.userAgent; document.write('user agent:<br />' + ua + '<br /><br />'); match = /WebKit\/([\w.]+)/.exec(ua); if (match) { document.write('Webkit Kernal<br />'); document.write('Version: ' + match[1]); } else { document.write('Not Webkit Kernal'); }
使用的正则表达式是/WebKit\/([\w.]+)/,表示包含"Webkit"及分隔符"/",并且捕捉"/"之后的字符,直到空格为止,作为版本号。(\w匹配字母或数字或下划线或汉字等。)
IE内核浏览器的描述字符串中包含了"MSIE",版本号紧跟着"MSIE"关键字,中间用空格分隔。因此,我们可以用下面的代码判断浏览器是否为IE内核,并提取版本号:
ua = window.navigator.userAgent; document.write('user agent:<br />' + ua + '<br /><br />'); match = /MSIE ([\w.]+)/.exec(ua); if (match) { document.write('IE Kernal<br />'); document.write('Version: ' + match[1]); } else { document.write('Not IE Kernal'); }
使用的正则表达式是/MSIE([\w.]+)/,表示包含"MSIE"及空格,并且捕捉空格之后的字符,直到下一个空格为止,作为版本号。
MozillaFirefox描述字符串中包含了"Mozilla",版本号出现在在"rv:"之后(Mozilla关键字之后也有版本号,但rv之后的版本号更细化一些)。因此,我们可以用下面的代码判断浏览器是否为Mozilla内核,并提取版本号:
ua = window.navigator.userAgent; document.write('user agent:<br />' + ua + '<br /><br />'); match = /Mozilla(?:.*? rv:([\w.]+))/.exec(ua); if (match) { document.write('Mozilla Kernal<br />'); document.write('Version: ' + match[1]); } else { document.write('Not Mozilla Kernal'); }
使用的正则表达式是/Mozilla(?:.*?rv:([\w.]+))/,表示包含"Mozilla",并且捕捉"rv:"之后的字符,直到下一个空格为止,作为版本号。
Opera描述字符串中包含了"Opera",版本号出现在在"Version/"之后(同样,Opera关键字之后也有版本号,但"Version"之后的版本号更细化一些)。因此,我们可以用下面的代码判断浏览器是否为Opera内核,并提取版本号:
ua = window.navigator.userAgent; document.write('user agent:<br />' + ua + '<br /><br />'); match = /Opera(?:.*Version)\/([\w.]+)/.exec(ua); if (match) { document.write('Opera Kernal<br />'); document.write('Version: ' + match[1]); } else { document.write('Not Opera Kernal'); }
使用的正则表达式是/Opera(?:.*Version)\/([\w.]+)/,表示包含"Opera",并且捕捉"Version/"之后的字符,直到下一个空格为止,作为版本号。
将以上针对不同浏览器的代码串联起来,就可以实现jQuery.browser了。但jQuery中的实现更具有技巧性一些。下面是与jQuery中的实现比较接近的写法:
$ = function() { function uaMatch(ua) { ua = ua.toLowerCase(); var match = rwebkit.exec(ua) || ropera.exec(ua) || rmsie.exec(ua) || ua.indexOf("compatible") < 0 && rmozilla.exec(ua) || []; return { browser : match[1] || "", version : match[2] || "0" }; } var rwebkit = /(webkit)\/([\w.]+)/, ropera = /(opera)(?:.*version)?[ \/]([\w.]+)/, rmsie = /(msie) ([\w.]+)/, rmozilla = /(mozilla)(?:.*? rv:([\w.]+))?/, browser = {}, ua = window.navigator.userAgent, browserMatch = uaMatch(ua); if (browserMatch.browser) { browser[browserMatch.browser] = true; browser.version = browserMatch.version; } return { browser: browser } }();
将这个JS文件命名为"jquery-browser.js",并在html中引用它:
<script type="text/javascript" src="jquery-browser.js"></script> <script> document.write('$.browser.webkit: ' + $.browser.webkit + '<br />'); document.write('$.browser.opera: ' + $.browser.opera + '<br />'); document.write('$.browser.msie: ' + $.browser.msie + '<br />'); document.write('$.browser.mozilla: ' + $.browser.mozilla + '<br />'); document.write('$.browser.version: ' + $.browser.version + '<br />'); </script>
效果与直接引用jquery.js是相同的。
让我们注意几个不同之处:
1.userAgent被转为小写字母进行匹配,避免了大小写的影响;
2.判断Mozilla时增加了ua.indexOf("compatible")<0,这是为了排除一些声称兼容Mozilla的浏览器的影响(比如IE8.0),一些搜索引擎的爬虫也经常声称兼容Mozilla;
3.检测Opera和Mozilla的正则表达式用"?"标明"rv"或"Version"是可有可无的,这可能是为了兼容不同的Opera和Mozilla内核浏览器(或较老的版本);
4.match捕捉的组有两个,第一个是浏览器内核名称,第二个是版本号,实现同时提取浏览器内核名称和版本号,减少了代码量。
以上就是jQuery.briwser的相对完整的实现了。主要的技巧是使用window.navigator.userAgent获取浏览器的描述字符串,以及通过正则表达式从该字符中提取信息。