热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

笑问客从何处来浏览器检测vs.特性检测

之所以说浏览器类型检测比较尴尬,是因为有了一个打对台的东东,但是又不可能完全被替代,就是粒度更小的浏览器特性检测。所以现在就成了两者共存的

之所以说浏览器类型检测比较尴尬,是因为有了一个打对台的东东,但是又不可能完全被替代,就是粒度更小的浏览器特性检测。

所以现在就成了两者共存的情况,虽然根据特性来判断更为准确,但是浏览器类型往往又是开发者判断的首选,而且较为简单明了。

还是和以前一样,站在巨人的肩膀上,利用各个js的框架源码,逐一分析比较一下。

注:采用的框架版本:prototype-1.6.1, mootools-1.2.4, jquery-1.4.2, ext-3.2.0, yui-3.1.0, dojo-1.4.2

prototype:


Browser : (function() {var ua = navigator.userAgent;var isOpera = Object.prototype.toString.call(window.opera) == '[object Opera]';return {IE : !!window.attachEvent && !isOpera,Opera : isOpera,WebKit : ua.indexOf('AppleWebKit/') > -1,Gecko : ua.indexOf('Gecko') > -1 && ua.indexOf('KHTML') === -1,MobileSafari : /Apple.*Mobile.*Safari/.test(ua)}
})(),
BrowserFeatures : {XPath : !!document.evaluate,SelectorsAPI : !!document.querySelector,ElementExtensions : (function() {var constructor = window.Element || window.HTMLElement;return !!(constructor && constructor.prototype);})(),SpecificElementExtensions : (function() {if (typeof window.HTMLDivElement !== 'undefined')return true;var div = document.createElement('div');var form = document.createElement('form');var isSupported = false;if (div['__proto__'] && (div['__proto__'] !== form['__proto__'])) {isSupported = true;}div = form = null;return isSupported;})()
}

  • 浏览器检测
    1. var isOpera = Object.prototype.toString.call(window.opera) == '[object Opera]',较常见的是var isOpera == !!window.opera,当然这个不够准确,因为我们可以在window下定义一个opera变量,所以采用前一种写法更加准确。
    2. window.attachEvent这个绑定事件的方法只有在ie及opera中支持,其余的都是采用addEventListener,因此可以用来判别是否是ie,不过稍稍有点奇怪的是,这里为什么就不怕用户自己加个attachEvent变量,如果采用约定俗成的话,那其实!!window.opera也足够了。
    3. webkit, gecko这些都是采用最常见的useragent字符串检测。
  • 特性检测
    1. XPath,document.evaluate会根据传入的path返回XPathResult对象,XPath的语法详见这里,除了ie外的主流浏览器基本都支持。
    2. SelectorsAPI,众多js selector,sizzle,peppy之类的终结者,新一代的浏览器,ff3.5,saf4,chrome,op10,嗯,还有ie8,都已经支持。
    3. ElementExtensions,大家对Object.prototype应该很熟悉了,这就是在DOM中是否允许扩展prototype,毫不意外,出局的又是ie。

mootools:


var Browser = $merge({Engine : {name : 'unknown',version : 0},Platform : {name : (window.orientation != undefined) ? 'ipod': (navigator.platform.match(/mac|win|linux/i) || ['other'])[0].toLowerCase()},Features : {xpath : !!(document.evaluate),air : !!(window.runtime),query : !!(document.querySelector)},Plugins : {},Engines : {presto : function() {return (!window.opera) ? false : ((arguments.callee.caller) ? 960 : ((document.getElementsByClassName)? 950 : 925));},trident : function() {return (!window.ActiveXObject) ? false : ((window.XMLHttpRequest) ? ((document.querySelectorAll) ? 6 : 5): 4);},webkit : function() {return (navigator.taintEnabled) ? false : ((Browser.Features.xpath)? ((Browser.Features.query) ? 525 : 420) : 419);},gecko : function() {return (!document.getBoxObjectFor && window.mozInnerScreenX == null) ? false: ((document.getElementsByClassName) ? 19 : 18);}}
}, Browser || {});
Browser.Platform[Browser.Platform.name] = true;
Browser.detect = function() {for (var engine in this.Engines) {var version = this.Engines[engine]();if (version) {this.Engine = {name : engine,version : version};this.Engine[engine] = this.Engine[engine + version] = true;break;}}return {name : engine,version : version};
};
Browser.detect();
Browser.Request = function() {return $try(function() {return new XMLHttpRequest();}, function() {return new ActiveXObject('MSXML2.XMLHTTP');}, function() {return new ActiveXObject('Microsoft.XMLHTTP');});
};
Browser.Features.xhr = !!(Browser.Request());
Browser.Plugins.Flash = (function() {var version = ($try(function() {return navigator.plugins['Shockwave Flash'].description;}, function() {return new ActiveXObject('ShockwaveFlash.ShockwaveFlash').GetVariable('$version');}) || '0 r0').match(/\d+/g);return {version : parseInt(version[0] || 0 + '.' + version[1], 10) || 0,build : parseInt(version[2], 10) || 0};
})();

  • 浏览器检测
    1. 多了平台的判断,这在某些情况下也还是有必要,因为不同平台的同一浏览器可能表现不一样,特别是手持终端平台。
    2. 这里与常见的浏览器类型版本不同的是判断的浏览器渲染引擎,presto是opera的专用,同样trident是ie家族的,使用webkit的就有很多,著名的如safari,chrome,gecko著名的是ff。但是用特征判断引擎的版本就不是很准确,因为版本在不断更新,如果需要判断引擎版本,还是推荐useragent分析,当然,实际上我们只关心引擎的大版本,如presto2,presto3,具体的版本号其实没有什么意义。
  • 特性检测
    1. 特性里加了是否支持xhr,目前绝大多数浏览器,包括手机平台的,都支持xhr,所以个人觉得可有可无。
    2. 插件判断加入是否安装flash,两个不同函数分别对应非ie和ie,但是要注意的是ie下有navigator.plugins这个对象,只是是个空对象。

jquery:


jquery = {// ...uaMatch : function(ua) {var ret = {browser : ""};ua = ua.toLowerCase();if (/webkit/.test(ua)) {ret = {browser : "webkit",version : /webkit[\/ ]([\w.]+)/};} else if (/opera/.test(ua)) {ret = {browser : "opera",version : /version/.test(ua) ? /version[\/ ]([\w.]+)/ : /opera[\/ ]([\w.]+)/};} else if (/msie/.test(ua)) {ret = {browser : "msie",version : /msie ([\w.]+)/};} else if (/mozilla/.test(ua) && !/compatible/.test(ua)) {ret = {browser : "mozilla",version : /rv:([\w.]+)/};}ret.version = (ret.version && ret.version.exec(ua) || [0, "0"])[1];return ret;},browser : {}
};
browserMatch = jQuery.uaMatch(userAgent);
if (browserMatch.browser) {jQuery.browser[browserMatch.browser] = true;jQuery.browser.version = browserMatch.version;
}
// Deprecated, use jQuery.browser.webkit instead
if (jQuery.browser.webkit) {jQuery.browser.safari = true;
}
// ...
(function() {jQuery.support = {};var root = document.documentElement, script = document.createElement("script"), div = document.createElement("div"), id ="script" + now();div.style.display = "none";div.innerHTML ='
a'; var all = div.getElementsByTagName("*"), a = div.getElementsByTagName("a")[0]; if (!all || !all.length || !a) { return; } jQuery.support = { leadingWhitespace : div.firstChild.nodeType === 3, tbody : !div.getElementsByTagName("tbody").length, htmlSerialize : !!div.getElementsByTagName("link").length, style : /red/.test(a.getAttribute("style")), hrefNormalized : a.getAttribute("href") === "/a", opacity : /^0.55$/.test(a.style.opacity), cssFloat : !!a.style.cssFloat, checkOn : div.getElementsByTagName("input")[0].value === "on", optSelected : document.createElement("select").appendChild(document.createElement("option")).selected, parentNode : div.removeChild(div.appendChild(document.createElement("div"))).parentNode === null, deleteExpando : true, checkClone : false, scriptEval : false, noCloneEvent : true, boxModel : null }; script.type = "text/Javascript"; try { script.appendChild(document.createTextNode("window." + id + "=1;")); } catch (e) { } root.insertBefore(script, root.firstChild); if (window[id]) { jQuery.support.scriptEval = true; delete window[id]; } try { delete script.test; } catch (e) { jQuery.support.deleteExpando = false; } root.removeChild(script); if (div.attachEvent && div.fireEvent) { div.attachEvent("onclick", function click() { jQuery.support.noCloneEvent = false; div.detachEvent("onclick", click); }); div.cloneNode(true).fireEvent("onclick"); } div = document.createElement("div"); div.innerHTML = ''; var fragment = document.createDocumentFragment(); fragment.appendChild(div.firstChild); jQuery.support.checkClone = fragment.cloneNode(true).cloneNode(true).lastChild.checked; jQuery(function() { var div = document.createElement("div"); div.style.width = div.style.paddingLeft = "1px"; document.body.appendChild(div); jQuery.boxModel = jQuery.support.boxModel = div.offsetWidth === 2; document.body.removeChild(div).style.display = 'none'; div = null; }); var eventSupported = function(eventName) { var el = document.createElement("div"); eventName = "on" + eventName; var isSupported = (eventName in el); if (!isSupported) { el.setAttribute(eventName, "return;"); isSupported = typeof el[eventName] === "function"; } el = null; return isSupported; }; jQuery.support.submitBubbles = eventSupported("submit"); jQuery.support.changeBubbles = eventSupported("change"); // release memory in IE root = script = div = all = a = null; })();

  • 浏览器检测
    1. 很传统的useragent字符串检测。
    2. 原来的safari被webkit代替,估计是因为chrome的强势出现。
  • 特性检测
    1. leadingWhitespace,ie中使用innnerHTML会将头部的空格自动去除,注意:尾部不会。
    2. tbody,如果table中没有tbody,则自动插入。这本来是ie的特性,但现在ie8的出现让情况复杂了,ie8不会自动插入,所以这时候就体现出特性检测的优势了,因为拥有更细的粒度,也就更为准确。
    3. htmlSerialize,源码中的注释有些错误,其实不是包装元素的问题,而是ie下将link等同于头部空格处理了,只需要将link挪后面或者在前面加上点什么就可以。
    4. style,getAttribute("style")返回style的字符串,但ie下是返回一个object,要取字符串的话用style.cssText。ie8又额外跳了出来,大家已经适应了ie的特殊性,这时候ie开始慢慢向标准靠拢,反而有点不习惯。
    5. hrefNormalized,getAttribute("href"),ie会在前面加入访问的url。同时,没错,你猜对了,ie8又是例外,我们应该渐渐感受到微软的诚意,尽管这一天来得太晚。
    6. opacity,这个应该比较熟悉,ie下可用滤镜实现,其余的也可以用特定样式,如-webkit-opacity,-moz-opacity。
    7. cssFloat,有一些css属性在css中与js中的名称不完全一样,这个就是一例,css中的float,ie中用styleFloat对应,其余的用cssFloat对应,具体这一类的情况我们在以后的获取样式中还会讲到。
    8. checkOn,除webkit引擎之外的浏览器,checkbox的默认值为"on"。
    9. optSelected,除webkit及ie外的浏览器,option的selected默认值为true,目前测试mac下的chrome例外,估计新版的532.9的webkit修复了这个bug已经。
    10. parentNode,除ie外的浏览器,removeNode的parentNode为空。
    11. deleteExpando,除ie外的浏览器,delete一个未定义的属性返回true。
    12. checkClone,除webkit外的浏览器,调用fragment的cloneNode时,checkbox的状态并未克隆,目前测试mac下的chrome例外,估计新版的532.9的webkit修复了这个bug已经。
    13. scriptEval,除ie外的浏览器可以像操纵普通dom元素一样对script元素使用appendChild,ie用script.text代替。
    14. noCloneEvent,ie调用cloneNode会将事件响应函数也复制过去,不是很合理。
    15. boxModel,盒模型就不解释了。
    16. submitBubbles,changeBubbles,ff用添加onevent属性,检查是否函数,其余的用简单的in来检测元素是否支持该事件响应,这一妙招来自于Detecting event support without browser sniffing。

ext:


var ua = navigator.userAgent.toLowerCase(),check = function(r){return r.test(ua);},DOC = document,isStrict = DOC.compatMode == "CSS1Compat",isOpera = check(/opera/),isChrome = check(/\bchrome\b/),isWebKit = check(/webkit/),isSafari = !isChrome && check(/safari/),isSafari2 = isSafari && check(/applewebkit\/4/), // unique to Safari 2isSafari3 = isSafari && check(/version\/3/),isSafari4 = isSafari && check(/version\/4/),isIE = !isOpera && check(/msie/),isIE7 = isIE && check(/msie 7/),isIE8 = isIE && check(/msie 8/),isIE6 = isIE && !isIE7 && !isIE8,isGecko = !isWebKit && check(/gecko/),isGecko2 = isGecko && check(/rv:1\.8/),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);

  • 浏览器检测
    1. 代码只用变量,但比jquery,并无甚不同,yui亦如是。(浪花只开一时,但比千年石,并无甚不同,流云亦如此,庆余年中的句子,个人非常喜欢,借用一下)
  • 特性检测
    1. isStrict,document.compatMode是否为CSS1Compat来判断是否是严格模式,但我在一篇文章中看到说这个判断并不准确,具体记不起来,留待日后找到再补。
    2. isSecure,采用http还是https访问。

yui:


Y.UA = function() {var numberify = function(s) {var c = 0;return parseFloat(s.replace(/\./g, function() {return (c++ == 1) ? '' : '.';}));}, win = Y.config.win, nav = win && win.navigator, o = {ie : 0,opera : 0,gecko : 0,webkit : 0,mobile : null,air : 0,caja : nav && nav.cajaVersion,secure : false,os : null}, ua = nav && nav.userAgent, loc = win && win.location, href = loc && loc.href, m;o.secure = href && (href.toLowerCase().indexOf("https") === 0);if (ua) {if ((/windows|win32/i).test(ua)) {o.os = 'windows';} else if ((/macintosh/i).test(ua)) {o.os = 'macintosh';} else if ((/rhino/i).test(ua)) {o.os = 'rhino';}if ((/KHTML/).test(ua)) {o.webkit = 1;}m = ua.match(/AppleWebKit\/([^\s]*)/);if (m && m[1]) {o.webkit = numberify(m[1]);if (/ Mobile\//.test(ua)) {o.mobile = "Apple";} else {m = ua.match(/NokiaN[^\/]*|Android \d\.\d|webOS\/\d\.\d/);if (m) {o.mobile = m[0];}}m=ua.match(/Chrome\/([^\s]*)/);if (m && m[1]) {o.chrome = numberify(m[1]); // Chrome} else {m = ua.match(/AdobeAIR\/([^\s]*)/);if (m) {o.air = m[0];}}}if (!o.webkit) {m = ua.match(/Opera[\s\/]([^\s]*)/);if (m && m[1]) {o.opera = numberify(m[1]);m = ua.match(/Opera Mini[^;]*/);if (m) {o.mobile = m[0];}} else { // not opera or webkitm = ua.match(/MSIE\s([^;]*)/);if (m && m[1]) {o.ie = numberify(m[1]);} else { // not opera, webkit, or iem = ua.match(/Gecko\/([^\s]*)/);if (m) {o.gecko = 1; // Gecko detected, look for revisionm = ua.match(/rv:([^\s\)]*)/);if (m && m[1]) {o.gecko = numberify(m[1]);}}}}}}return o;
}();

  • 浏览器检测
    1. 也是useragent字符串检测,不过变量的值即表示该浏览器的版本号,如果取不到版本号则默认为1,这样避免了如ie6,ie7,ie8之类多个变量,减少变量使用,更为清晰。
  • 特性检测
    1. secure

dojo:


var d = dojo;
var n = navigator;
var dua = n.userAgent, dav = n.appVersion, tv = parseFloat(dav);
if (dua.indexOf("Opera") >= 0) {d.isOpera = tv;
}
if (dua.indexOf("AdobeAIR") >= 0) {d.isAIR = 1;
}
d.isKhtml = (dav.indexOf("Konqueror") >= 0) ? tv : 0;
d.isWebKit = parseFloat(dua.split("WebKit/")[1]) || undefined;
d.isChrome = parseFloat(dua.split("Chrome/")[1]) || undefined;
d.isMac = dav.indexOf("Macintosh") >= 0;
var index = Math.max(dav.indexOf("WebKit"), dav.indexOf("Safari"), 0);
if (index && !dojo.isChrome) {d.isSafari &#61; parseFloat(dav.split("Version/")[1]);if (!d.isSafari || parseFloat(dav.substr(index &#43; 7)) <&#61; 419.3) {d.isSafari &#61; 2;}
}
if (dua.indexOf("Gecko") >&#61; 0 && !d.isKhtml && !d.isWebKit) {d.isMozilla &#61; d.isMoz &#61; tv;
}
if (d.isMoz) {d.isFF &#61; parseFloat(dua.split("Firefox/")[1] || dua.split("Minefield/")[1]) || undefined;
}
if (document.all && !d.isOpera) {d.isIE &#61; parseFloat(dav.split("MSIE ")[1]) || undefined;var mode &#61; document.documentMode;if (mode && mode !&#61; 5 && Math.floor(d.isIE) !&#61; mode) {d.isIE &#61; mode;}
}
if (dojo.isIE && window.location.protocol &#61;&#61;&#61; "file:") {dojo.config.ieForceActiveXXhr &#61; true;
}
d.isQuirks &#61; document.compatMode &#61;&#61; "BackCompat";
d.locale &#61; dojo.config.locale || (d.isIE ? n.userLanguage : n.language).toLowerCase();

  • 浏览器检测
    1. useragent字符串检测。
    2. ie8的X-UA-Compatible引入带来了一定的麻烦&#xff0c;需要综合document.documentMode来考虑。
  • 特性检测
    1. isQuirks。
    2. locale&#xff0c;在1.4.2中新加入了语言。

通过以上的代码&#xff0c;我们可以总结出以下几点&#xff1a;

  1. 浏览器与特性检测并不矛盾&#xff0c;可以同时存在。
  2. 有些框架着重于引擎版本&#xff0c;有些着重于浏览器版本&#xff0c;基本上每个引擎都对应于一个主要浏览器&#xff0c;webkit除外&#xff0c;有safari和chrome&#xff0c;我们就单独处理一下。
  3. 为了判断兼容性&#xff0c;一般都有平台信息&#xff0c;但缺少语言信息。
  4. 有各种特性检测&#xff0c;有对各种特性的支持判断&#xff0c;也有基于某些特殊浏览器bug的兼容判断。
  5. 对新的HTML5的一些特性检测好像都没有&#xff0c;可以考虑加入。

综合网上的一些代码得出的个人版本


var win &#61; window, doc &#61; win.document, nav &#61; win.navigator, root &#61; doc.documentElement, div &#61; doc.createElement(&#39;div&#39;), bs, frag, id, ua &#61;navigator.userAgent, ots &#61; Object.prototype.toString;
function has(p, o) {o &#61; o || win;if (p in o) {try {delete o[p];} catch (e) {}return p in o;}
};
function ver(split) {var s &#61; ua.split(split)[1];return s && (s &#61; s.split(&#39;.&#39;)) && parseFloat(s.shift() &#43; &#39;.&#39; &#43; s.join(&#39;&#39;)) || 1;
};
function hasEvent(e) {e &#61; "on" &#43; e;var has &#61; (e in div);if (!has) {div.setAttribute(e, "return;");has &#61; typeof div[e] &#61;&#61;&#61; "function";}return has;
};
// 为了保证特性检测的独立性&#xff0c;所以不依靠浏览器判断
div.innerHTML &#61;&#39;
&#39;; bs &#61; { trident : -[1,] ? 0 : ScriptEngineMinorVersion(), // 考虑像mootools那样用window.ActiveXObject来判断&#xff0c;但实质上这和判断userAgent一样的&#xff0c;都是可以由用户更改的&#xff0c;所以取了这个最短判断&#xff0c;至少目前可用 webkit : !has(&#39;taintEnabled&#39;, nav) ? ver(&#39;WebKit/&#39;) : 0, gecko : win.crypto && ots.call(win.crypto) &#61;&#61;&#61; &#39;[object Crypto]&#39; ? ver(&#39;rv:&#39;) : 0, presto : win.opera && ots.call(win.opera) &#61;&#61;&#61; &#39;[object Opera]&#39; ? ver(&#39;Presto/&#39;) : 0, gchrome : has(&#39;chrome&#39;) ? ver(&#39;Chrome/&#39;) : 0, safari : /a/.__proto__ &#61;&#61; &#39;//&#39; ? ver(&#39;Version/&#39;) : 0, // mac,win下ok ie : document.documentMode, platform : (nav.platform.toLowerCase().match(/mac|win|linux/) || [&#39;&#39;])[0], lang : (nav.language || nav.browserLanguage).toLowerCase(), // feature detect strict : doc.compatMode &#61;&#61;&#61; &#39;CSS1Compat&#39;, https : /^https/i.test(win.location.protocol), // xpath: !!doc.evaluate // query: !!doc.querySelector, // style 没有太大意义&#xff0c;应该使用通用的a.style.cssText querySelector : has(&#39;querySelector&#39;, doc), // in opera HTMLElement.prototype will lead an error domExtensible : win.HTMLDivElement && (&#39;prototype&#39; in win.HTMLDivElement) ? 2 : win.HTMLElement && (&#39;prototype&#39; in win.HTMLElement) ? 1 : 0, msging : has(&#39;postMessage&#39;), storage : win.sessionStorage && ots.call(win.sessionStorage) &#61;&#61;&#61; &#39;[object Storage]&#39;, db : has(&#39;openDatabase&#39;), appCache : has(&#39;applicationCache&#39;), worker : win.Worker && ots.call(win.Worker) &#61;&#61;&#61; &#39;[object Worker]&#39;, geo : nav.geolocation && ots.call(nav.geolocation) &#61;&#61;&#61; &#39;[object Geolocation]&#39;, dragdrop : hasEvent(&#39;drag&#39;), offline : has(&#39;onLine&#39;, nav), cssTable : 0, rgba : 0, blankTrimmed : div.firstChild.nodeName &#61;&#61;&#61; &#39;A&#39;, hrefNormalized : div.getElementsByTagName(&#39;a&#39;)[0].getAttribute(&#39;href&#39;) &#61;&#61;&#61; &#39;/a&#39;, autoTbody : div.getElementsByTagName(&#39;tbody&#39;).length, scriptChild : 0, parentRemoved : !div.removeChild(div.firstChild).parentNode, optSeleted : div.getElementsByTagName(&#39;select&#39;)[0].appendChild(document.createElement(&#39;option&#39;)).selected, chkOn : div.lastChild.value &#61;&#61;&#61; &#39;on&#39;, chkCloned : 1, eventCloned : 0 // deleteExpando // boxModel:, // submitBubbles, changeBubbles }; if (div.attachEvent && div.fireEvent) { div.attachEvent("onclick", function click() { bs.eventCloned &#61; 1; div.detachEvent("onclick", click); }); div.cloneNode(true).fireEvent("onclick"); } frag &#61; doc.createDocumentFragment(); div.innerHTML &#61; &#39;&#39;; frag.appendChild(div.lastChild); bs.chkClone &#61; frag.cloneNode(true).lastChild.checked; frag &#61; doc.createElement(&#39;script&#39;); frag.type &#61; "text/Javascript"; id &#61; &#39;_&#39; &#43; new Date().getTime(); try { frag.appendChild(doc.createTextNode(&#39;window.&#39; &#43; id &#43; &#39;&#61;1;&#39;)); } catch (e) { } root.insertBefore(frag, root.firstChild); if (win[id]) { bs.scriptEval &#61; 1; delete win[id]; } root.removeChild(frag); try { div.style.display &#61; &#39;table&#39;; bs.cssTable &#61; div.style.display &#61;&#61;&#61; &#39;table&#39;; } catch(e) { } try { div.style.color &#61; &#39;rgba(0,0,0,1)&#39;; bs.rgba &#61; !div.style.color.indexOf(&#39;rgba&#39;); } catch(e) { } div &#61; flag &#61; null;

  • 浏览器检测
    1. 检测trident, webkit, gecko和presto这四大浏览器引擎及版本
    2. 检测chrome, safari等常用浏览器及版本
    3. trident属性和ie属性的区别&#xff0c;主要为了兼容ie8引入的X-UA-Compatible&#xff0c;trident指的是浏览器引擎版本&#xff0c;ie指的是当前浏览器渲染版本&#xff0c;通常以ie为比较标准。
    4. 检测win, mac, linux平台
    5. 加入当前浏览器使用语言
  • 特性检测
    1. strict, 是否使用严格模式。
    2. https, 是否使用https协议。
    3. querySelector, 是否提供querySelector函数。
    4. domExtensible, dom元素是否允许扩展&#xff0c;0不允许&#xff0c;1只允许HTMLElement&#xff0c;2可扩展各个HTMLElement子类。
    5. msging, 是否支持跨文档通信。
    6. storage, 是否支持本地存储。
    7. db, 是否支持本地数据库。
    8. worker, 是否支持worker。
    9. geo, 是否支持geolocation。
    10. dragdrop, 是否支持原生拖放。
    11. offline, 是否支持离线检测。
    12. cssTable, 是否支持css的table布局。
    13. rgba, 是否支持rgba。
    14. blankTrimmed, innerHTML是否会去掉空格。
    15. hrefNormalized, href值是否保持不变。
    16. autoTbody, 是否自动插入tbody。
    17. scriptChild&#xff0c;除ie外的浏览器可以像操纵普通dom元素一样对script元素使用appendChild&#xff0c;ie用script.text代替。
    18. parentRemoved&#xff0c;除ie外的浏览器&#xff0c;removeNode的parentNode为空。
    19. optSelected&#xff0c;除webkit及ie外的浏览器&#xff0c;option的selected默认值为true&#xff0c;目前测试mac下的chrome例外&#xff0c;估计新版的532.9的webkit修复了这个bug已经。
    20. chkOn&#xff0c;除webkit引擎之外的浏览器&#xff0c;checkbox的默认值为"on"。
    21. chkCloned&#xff0c;除webkit外的浏览器&#xff0c;调用fragment的cloneNode时&#xff0c;checkbox的状态并未克隆&#xff0c;目前测试mac下的chrome例外&#xff0c;估计新版的532.9的webkit修复了这个bug已经。
    22. eventCloned&#xff0c;ie调用cloneNode会将事件响应函数也复制过去&#xff0c;不是很合理。

通过对高手的代码学习解析&#xff0c;能从中提高一星半点对js的掌握。

个人评价&#xff1a;

ext:★

yui,dojo:★☆

prototype:★★

mootools:★★☆

jquery:★★★★

转:https://www.cnblogs.com/nozer0/archive/2010/03/24/1664443.html



推荐阅读
author-avatar
永不放弃2702935973
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有