先来看一段来自 ExtJS 框架的实际代码。在 3.0 beta 1 版本中,src/core/Ext.js 文件里对浏览器类型进行判断的实现方式如下:
ua = na vigator.userAgent.toLowerCase(),
check = function(r){
return r.test(ua);
},
isStrict = document.compatMode == "CSS1Compat",
isOpera = check(/opera/),
isChrome = check(/chrome/),
isWebKit = check(/webkit/),
isSafari = !isChrome && check(/safari/),
isSafari3 = isSafari && check(/version/3/),
isSafari4 = isSafari && check(/version/4/),
isIE = !isOpera && check(/msie/),
isIE7 = isIE && check(/msie 7/),
isIE8 = isIE && check(/msie 8/),
isGecko = !isWebKit && check(/gecko/),
isGecko3 = isGecko && check(/rv:1.9/),
isBorderBox = isIE && !isStrict,
isWindows = check(/windows|win32/),
isMac = check(/macintosh|mac os x/),
isAir = check(/adobeair/),
isLinux = check(/linux/),
isSecure = /^https/i.test(window.location.protocol);
而在 2.2.1 版本中(同样位于 source/core/ext.js),浏览器检测的实现手法则呈现了不同的风格:
var ua = na vigator.userAgent.toLowerCase();
var isStrict = document.compatMode == "CSS1Compat",
isOpera = ua.indexOf("opera") > -1,
isChrome = ua.indexOf("chrome") > -1,
isSafari = !isChrome && (/webkit|khtml/).test(ua),
isSafari3 = isSafari && ua.indexOf('webkit/5') != -1,
isIE = !isOpera && ua.indexOf("msie") > -1,
isIE7 = !isOpera && ua.indexOf("msie 7") > -1,
isIE8 = !isOpera && ua.indexOf("msie 8") > -1,
isGecko = !isSafari && !isChrome && ua.indexOf("gecko") > -1,
isGecko3 = isGecko && ua.indexOf("rv:1.9") > -1,
isBorderBox = isIE && !isStrict,
isWindows = (ua.indexOf("windows") != -1 || ua.indexOf("win32") != -1),
isMac = (ua.indexOf("macintosh") != -1 || ua.indexOf("mac os x") != -1),
isAir = (ua.indexOf("adobeair") != -1),
isLinux = (ua.indexOf("linux") != -1),
isSecure = window.location.href.toLowerCase().indexOf("https") === 0;
两相对比可以发现,3.0 版本引入了统一的 check 函数,借助正则表达式进行浏览器特征匹配,代码更加简洁且具备更优的可读性;相比之下,2.2.1 版本沿用传统的 indexOf 字符串匹配方式,逻辑上更为直白。此外,在 isSafari 和 isChrome 的判定逻辑上也存在细微差别——3.0 明确通过 !isChrome 排除 Chrome 对 Safari 判断的干扰,而 2.2.1 则结合 !isChrome 与正则检测 webkit|khtml 来实现。这些细节变化,折射出 ExtJS 框架在版本演进过程中对浏览器检测逻辑的持续优化与精雕细琢。
