javascript 特徵偵測技術

來源:互聯網
上載者:User

這種新式的技術最先由jQuery搞出來的,接著Prototype與mootools都支援了。這技術興起的原因是瀏覽器嗅探技術是不太可靠,如UserAgent很容易被偽造,如IE8的UserAgent就把許多瀏覽器的關鍵字包含進去,造成辯識困難。其他一些重要辯識手段,由於瀏覽器廠商對舊版本的升級與不斷推進新版本,許多都無效了。由於瀏覽器種類越來越多,版本也越來越多,看看Ext的核心檔案吧,真是有耐性,連Firefox與蘋果的各個版本都列出來,這東西會沒有止境地膨脹,為此特徵偵測技術應運而生。這東西只要是用來偵測瀏覽器工廠自作聰明添加的一些特徵,不用說,首當其衝是IE,如自動為table添加tbody,自動為innerHTML去除空白,自動為href屬性補全路徑……雖然有的的確很有用,如為table添加tbody能加快讀寫速度,但標準瀏覽器不這樣做,於是麻煩又來了……

innerHTML去除空白特性。按理講,innerHTML是IE搞出來的,其他瀏覽器應該完全按照IE的模式渲染才對不起,但它們總要搞出一點特殊來。不過,IE的innerHTML的確有不妥的地方。按微軟的思路,innerHTML是用來大規模產生DOM元素,如果有一些空白不是包圍在標籤之內,將會被忽略掉。這是很細心的處理。但標準瀏覽器則認為innerHTML產生的是頁面的一部分,空白也是,因此空白不會被忽略的。注意運行框的結果,1代表元素節點,3是文本節點,空白也是文本節點的一種。這種特徵,jQuery稱之為leadingWhitespace。

<br /><!doctype html><br /><html dir="ltr" lang="zh-CN"><br /> <head><br /> <meta charset="utf-8"/><br /> <title>特徵偵測技術 By 司徒正美</title><br /> <script type="text/javascript"><br /> window.onload = function(){<br /> var p = document.getElementById("p");<br /> p.innerHTML = " <span>你好!</span>"<br /> alert(p.firstChild.nodeType);<br /> }<br /> </script></p><p> </head><br /> <body><br /> <p id="p"></p><br /> </body><br /></html><br />

運行代碼

table自動插入tbody。在表格版面配置的年代,這特徵非常受用的。因為如果沒有tbody,table會在瀏覽器解析到閉合標籤時才顯示出來,如果起始標籤與閉合標籤相隔很完,換言之,這表格很大很長,使用者會看什麼也看不到。但有了tbody分段識別和顯示,避免了頁面長時間一片空白然後突然一下子內容全部出來的局面。不過,這隻因為IE渲染速度太慢的緣故,看看人家的opera與chrome……此特徵,jQuery就叫tbody,囧!

<br /><!doctype html><br /><html dir="ltr" lang="zh-CN"><br /> <head><br /> <meta charset="utf-8"/><br /> <meta http-equiv="X-UA-Compatible" content="IE=7"><br /> <title>特徵偵測技術 By 司徒正美</title><br /> <script type="text/javascript"><br /> window.onload = function(){<br /> var div = document.createElement("div");<br /> div.innerHTML = "<table></table>"<br /> document.body.appendChild(div);<br /> alert(div.getElementsByTagName("tbody").length,)<br /> }<br /> </script></p><p> </head><br /> <body></p><p> </body><br /></html><br />

運行代碼

object的子項目不可見特性。也就是說,雖然成功渲染了,但我們無法擷取裡面的這些東西,真是撞鬼了。如果做flash,要臨時改動一下參數……此特徵,jQuery稱之為objectAll。

<br /><!doctype html><br /><html dir="ltr" lang="zh-CN"><br /> <head><br /> <meta charset="utf-8"/><br /> <meta http-equiv="X-UA-Compatible" content="IE=7"><br /> <title>特徵偵測技術 By 司徒正美</title><br /> <script type="text/javascript"><br /> window.onload = function(){<br /> var div = document.createElement("div");<br /> div.innerHTML = "<object><param/><param/><param/></object>"<br /> document.body.appendChild(div);<br /> alert(div.getElementsByTagName("object")[0].children.length)<br /> alert(document.getElementsByTagName("param")[0])<br /> }<br /> </script></p><p> </head><br /> <body></p><p> </body><br /></html><br />

運行代碼

innerHTML序列化html字串特性。通常我們用innerHTML把一個符合html標籤格子的字串轉換為DOM元素,此過程jQuery稱之為序列化,但這序列化在IE中是不完整的,不能序列化為link元素。因此不要用innerHTML動態載入CSS檔案。此特徵在jQuery的名字叫htmlSerialize。

<br /><!doctype html><br /><html dir="ltr" lang="zh-CN"><br /> <head><br /> <meta charset="utf-8"/><br /> <title>特徵偵測技術 By 司徒正美</title><br /> <script type="text/javascript"><br /> window.onload = function(){<br /> var div = document.createElement("div");<br /> div.innerHTML = '<link href="http://www.cnblogs.com/Skins/marvin2/brown.css" rel="stylesheet" type="text/css" /> ';<br /> document.body.appendChild(div);<br /> alert(div.getElementsByTagName("link").length)<br /> }<br /> </script></p><p> </head><br /> <body><br /> <h1 id="top">司徒正美的部落格Ruby Louvre</h1><br /> <h3 id="tagline">如果網頁不是純白色,證明已成功載入我部落格的主題!</h3><br /> </body><br /></html><br />

運行代碼

最新發現(2009,12,11),IE也並不是不支援link元素的序列化,而是存在一些bug。見下面測試

<br /><!doctype html><br /><html dir="ltr" lang="zh-CN"></p><p> <head><br /> <meta charset="utf-8" /><br /> <title><br /> innerHTML bug By 司徒正美<br /> </title><br /> <script type="text/javascript"><br /> window.onload = function() {<br /> var div = document.createElement('div');<br /> div.innerHTML = '<link>';<br /> alert(div.innerHTML);<br /> // => ''<br /> div.innerHTML = '<div><link></div>';<br /> alert(div.innerHTML);<br /> // => '<div></div>'<br /> div.innerHTML = '<div><link></div>text';<br /> alert(div.innerHTML);<br /> // => '<div></div>text'<br /> div.innerHTML = 'text<link>'<br /> alert(div.innerHTML);<br /> // => 'text<link>'<br /> }<br /> </script><br /> </head></p><p> <body><br /> <h1 id="top"><br /> 司徒正美的部落格Ruby Louvre<br /> </h1><br /> <h3 id="tagline"><br /> 如果網頁不是純白色,證明已成功載入我部落格的主題!<br /> </h3><br /> </body></p><p></html><br />

運行代碼

getAttribute對style支援特性。IE會獲得一個對象,其他則獲得一個字串……至於setAttribue的情況可見我另一篇博文。此特徵在jQuery稱之為style,真是莫名其妙的命名啊!

<br /><!doctype html><br /><html dir="ltr" lang="zh-CN"><br /> <head><br /> <meta charset="utf-8"/><br /> <title>特徵偵測技術 By 司徒正美</title><br /> <script type="text/javascript"><br /> window.onload = function(){<br /> var div = document.createElement("div");<br /> div.innerHTML = '<a href="/a" style="color:red;">司徒正美</a>';<br /> document.body.appendChild(div);<br /> var a = div.getElementsByTagName("a")[0];<br /> alert(a.getAttribute("style"))<br /> }<br /> </script></p><p> </head><br /> <body></p><p> </body><br /></html><br />

運行代碼

自動補全url特性。IE會把img的src,a的href,form的action全部補全為絕對路徑,此bug可以用getAttribute的第二個參數搞定。此特徵在jQuery稱之為hrefNormalized。

<br /><!doctype html><br /><html dir="ltr" lang="zh-CN"><br /> <head><br /> <meta charset="utf-8"/><br /> <title>特徵偵測技術 By 司徒正美</title><br /> <meta http-equiv="X-UA-Compatible" content="IE=7"></p><p> <script type="text/javascript"><br /> window.onload = function(){</p><p> var a = document.getElementsByTagName("a")[0];<br /> var img = document.getElementsByTagName("img")[0];<br /> var form = document.getElementsByTagName("form")[0];<br /> alert("連結的href屬性為 "+ a.getAttribute("href"))<br /> alert("圖片的src屬性為 "+ img.getAttribute("src"))<br /> alert("表單的action屬性為 "+ form.getAttribute("action"))<br /> }<br /> </script></p><p> </head><br /> <body><br /> <a href="/rubylouvre">司徒正美</a><br /> <img src="/205314/o_iebug.jpg" /><br /> <form action="/rubylouvre"></form><br /> </body><br /></html><br />

運行代碼

動態解析指令碼特性。在標準瀏覽器中,如果為script添加文本節點,它會把裡面的內容解析為指令碼,IE則不行,要依賴其text屬性,詳見我另一篇博文《javascript 動態解析指令碼》。此特性,jQuery稱之為scriptEval。

<br /><!doctype html><br /><html dir="ltr" lang="zh-CN"><br /> <head><br /> <meta charset="utf-8"/><br /> <title>特徵偵測技術 By 司徒正美</title></p><p> <script type="text/javascript"><br /> window.onload = function(){<br /> var script = document.createElement("script");<br /> script.type = "text/javascript";<br /> try {<br /> script.appendChild( document.createTextNode( "window.rubylouvre=100" ) );<br /> } catch(e){}<br /> document.body.appendChild( script );<br /> if ( window.rubylouvre ) {<br /> alert( window.rubylouvre )<br /> delete window.rubylouvre;<br /> }<br /> document.body.removeChild( script );<br /> }<br /> </script></p><p> </head><br /> <body></p><p> </body><br /></html><br />

運行代碼

複製事件特性,指用cloneNode方法複製節點時,會連它上面的事件也複製了。jQuery稱之為noCloneEvent。

<br /><!doctype html><br /><html dir="ltr" lang="zh-CN"><br /> <head><br /> <meta charset="utf-8"/><br /> <title>特徵偵測技術 By 司徒正美</title><br /> <script type="text/javascript"><br /> window.onload = function(){<br /> var addEvent = (function () {<br /> if (document.addEventListener) {<br /> return function (el, type, fn) {<br /> el.addEventListener(type, fn, false);<br /> };<br /> } else {<br /> return function (el, type, fn) {<br /> el.attachEvent('on' + type, function () {<br /> return fn.call(el, window.event);<br /> });<br /> }<br /> }<br /> })();<br /> var div1 = document.createElement("div");<br /> div1.style.cssText = "width:200px;height:200px;background:blue";<br /> div1.innerHTML = "點我!"<br /> document.body.appendChild(div1);<br /> addEvent(div1,"click",function(){<br /> alert("這是div1的事件!")<br /> });<br /> var div2 = div1.cloneNode(true);<br /> div2.style.backgroundColor = "red";<br /> document.body.appendChild(div2);<br /> }<br /> </script></p><p> </head><br /> <body></p><p> </body><br /></html><br />

運行代碼

盒子模型特性,IE在不同的渲染模式下,盒子模型是不同的。標準的盒子模型,元素的總寬度等於=左邊界+左邊框+左補白+寬+右補白+右邊框+右邊界。怪異模式下,元素的總寬度=左邊界+寬+右邊界。換言之,怪異模式下,其寬會少一點。我們可以用offsetWidth來驗證,offsetWidth的定義可由解釋得一清二楚!jQuery稱之為boxModel。

<br /><html><br /> <head><br /> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/><br /> <title>特徵偵測技術 By 司徒正美</title><br /> <script type="text/javascript"><br /> window.onload = function(){<br /> var div = document.createElement("div");<br /> div.style.width = div.style.paddingLeft = "1px";<br /> document.body.appendChild( div );<br /> alert(div.offsetWidth)<br /> }<br /> </script></p><p> </head><br /> <body></p><p> </body><br /></html><br />

運行代碼

其他兩種cssStyle與opacity就不詳說了,IE下都有代替品。在Prototype還檢測瀏覽器對XPath,SelectorsAPI,Element,Element.prototype的支援,innerHTML在select、col、colgroup、frameset、html、title、style、table、tbody、thead、tfoot、tr、td、th中的讀寫情況。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.