上QQ阅读APP看书,第一时间看更新
第4章 浏览器嗅探与特征侦测
虽然浏览器嗅探现在已经不推荐了,但在某些场合我们还是需要的,比如一些统计脚本。而特征侦测是Prototype时期发展起来的一个技术,具体是判定某个原生对象有没有此方法或属性,有时严格一些,则会执行这个方法,看它有没有达到预期的值。在标准浏览器里,它们提供了document.implementation.hasfeature方法,可惜有Bug,不准确。在本书快成形时,W3C又推出了CSS.supports方法,显然大家都对这块非常重视。
4.1 判定浏览器
主流浏览器有五个:IE、Firefox、Opera、Chrome、Safari。早期所有框架都是通过navigator.userAgent 进行判定,与浏览器商斗智斗谋。显然外国的浏览器商还是有良心的,换是国内的,基本判定不出。
jQuery给出的解决方案,现在已移出jQuery本体,成为一个插件。
(function(jQuery, window, undefined) { "use strict"; var matched, browser; jQuery.uaMatch = function(ua) { ua = ua.toLowerCase(); var match = /(chrome)[ \/]([\w.]+)/.exec(ua) || /(webkit)[ \/]([\w.]+)/.exec(ua) || /(opera)(?:.*version|)[ \/]([\w.]+)/.exec(ua) || /(msie) ([\w.]+)/.exec(ua) || ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec(ua) || []; var platform_match = /(ipad)/.exec(ua) || /(iphone)/.exec(ua) || /(android)/.exec(ua) || []; return { browser: match[ 1 ] || "", version: match[ 2 ] || "0", platform: platform_match[0] || "" }; }; matched = jQuery.uaMatch(window.navigator.userAgent); browser = {}; if (matched.browser) { browser[ matched.browser ] = true; browser.version = matched.version; } if (matched.platform) { browser[ matched.platform ] = true } // Chrome is Webkit, but Webkit is also Safari. if (browser.chrome) { browser.webkit = true; } else if (browser.webkit) { browser.safari = true; } jQuery.browser = browser; })(jQuery, window);
mass Framework给出的解决方案如下。
//https://github.com/RubyLouvre/mass-Framework/blob/1.4/more/brower.js define("brower", function( ){ var w = window,ver = w.opera ? (opera.version().replace(/\d$/, "") - 0) : parseFloat((/(?:IE |fox\/|ome\/|ion\/)(\d+\.\d)/. exec(navigator.userAgent) || [,0])[1]); return { //测试是否为IE或内核为trident,是则取得其版本号 ie: !!w.VBArray && Math.max(document.documentMode||0, ver),//内核trident //测试是否为Firefox,是则取得其版本号 firefox: !!w.netscape && ver,//内核Gecko //测试是否为Opera,是则取得其版本号 opera: !!w.opera && ver,//内核 Presto 9.5为Kestrel 10为Carakan //测试是否为Chrome,是则取得其版本号 chrome: !! w.chrome && ver ,//内核V8 //测试是否为Safari,是则取得其版本号 safari: /apple/i.test(navigator.vendor) && ver// 内核 WebCore } });
mass成形较晚,是使用特征侦测实现的。
特征侦测的好处是浏览器不会随意去掉某一个功能,不过要注意不要使用标准属性与方法做判定依据。每个浏览器都有自己的私有实现,我们用它们做判定好了。下面是我收集的其他一些判定方法。
ie = !!document.recalc ie = !!window.VBArray ie = !!window.ActiveXObject ie = !!window.createPopup; ie = /*@cc_on!@*/!1; ie = document.expando;//document.all在opera firefox的古老版本也存在 ie = (function() {//IE10中失效 var v = 3, div = document.createElement('div'); while (div.innerHTML = '<!--[if gt IE ' + (++v) + ']><br><![endif]-->', div.innerHTML ) ; return v > 4 ? v : !v; }()); ie678 = !+"\v1"; ie678 = !-[1, ]; ie678 = '\v' == 'v'; ie678 = ('a~b'.split(/(~)/))[1] == "b" ie678 = 0.9.toFixed(0) == "0" ie678 = /\w/.test('\u0130') //由群里的abcd友情提供 ie8 = window.toStaticHTML ie9 = window.msPerformance ie678 = 0//@cc_on+1; ie67 = !"1"[0] //利用IE6或IE5的字符串不能使用数组下标的特征 ie8 = !!window.XDomainRequest; ie9 = document.documentMode && document.documentMode === 9; //基于条件编译的嗅探脚本,IE会返回其JS引擎的版本号,非IE返回0 var ieVersion = eval("''+/*@cc_on" + " @_jscript_version@*/-0") * 1 ie9 = ieVersion === 5.9 ie8 = ieVersion === 5.8 ie7 = ieVersion === 5.7 ie6 = ieVersion === 5.6 ie5 = ieVersion === 5.5 ie10 = window.navigator.msPointerEnabled ie11 = '-ms-scroll-limit' in document.documentElement.style opera = !!window.opera; //https://developer.mozilla.org/En/Windows_Media_in_Netscape firefox = !!window.GeckoActiveXObject firefox = !!window.netscape //包括firefox firefox = !!window.Components firefox = !!window.updateCommands safari = !!(navigator.vendor && navigator.vendor.match(/Apple/)) safari = window.openDatabase && !window.chrome; chrome = !!(window.chrome && window.google) 移动设备的相关判定。这个建议看jquery mobile与zepto的源代码。 isIPhone = /iPhone/i.test(navigator.userAgent); isIPhone4 = window.devicePixelRatio >= 2//在网页中,pixel与point比值称为device-pixel-ratio, 普通设备都是1,iPhone 4是2,有些Android机型是1.5 //http://blog.webcreativepark.net/2011/01/25-173502.html isIPad = /iPad/i.test(navigator.userAgent); isAndroid = /android/i.test(navigator.userAgent); isIOS = isIPhone || isIPad ;
国内的浏览器判定可以看Tangram或qwrap。它们基本是IE,webkit内核或blink内核。