先說一點心得css
IE8瀏覽器 getAttribute("className")能夠獲取class的值html
火狐 getAttribute("class")能夠獲取class的值瀏覽器
getElementById("c").className 均可以測試
下邊是轉載的:this
簡單來講,就是IE8以前的版本,需使用getAttribute('className')才能得到class屬性的值,FF及IE8以後的版本則是W3C 的標準getAttribute('class')。spa
這是由於IE 混淆了 DOM 對象屬性(property)及 HTML 標籤屬性(attribute),形成了對 setAttribute、getAttribute 的不正確實現。設計
根據 DOM (Core) Level 1 規範中的描述,getAttribute 與 setAttribute 爲 Element 接口下的方法,其功能分別是經過 "name" 獲取和設置一個元素的屬性(attribute)值。getAttribute 方法會以字符串的形式返回屬性值,若該屬性沒有設定值或缺省值則返回空字符串。setAttribute 方法則無返回值。
在 DOM Level 2 規範中,則更加明確了 getAttribute 與 setAttribute 方法參數中的 "name" 的類型爲 DOMString,setAttribute 方法參數中的 "value" 的類型爲 DOMString,getAttribute 的返回值類型也爲 DOMString。code
DOMString getAttribute(in DOMString name); void setAttribute(in DOMString name, in DOMString value) raises(DOMException);
HTML 文檔中的 DOM 對象的屬性(property)被定義在 DOM (HTML) 規範中。這個規範中明肯定義了 document 對象以及全部標準的 HTML 元素所對應的 DOM 對象擁有的屬性及方法。
由於在早期的 DOM Level 0 階段,某些 HTML 標籤的屬性會將其值暴露給對應的 DOM 對象的屬性,如 HTML 元素的 id 屬性與其對應的 DOM 對象的 id 屬性會保持一種同步關係,然而這種方式目前已經廢棄,這是因爲它不能被擴展到全部可能存在的 XML 的屬性名稱。W3C 建議使用 DOM (Core) 中 Element 接口上定義的通用方法去獲取(getting)、設置(setting)及刪除(removing)元素的屬性。orm
舉例來講,在一個 HTML 文檔中存在一個 SPAN 元素,根據 DOM (HTML) 規範,SPAN 元素在頁面中生成一個相對應的對象,這個對象派生自 HTMLElement 接口,而 HTMLElement 接口則繼承自 Element 接口。HTMLElement 接口中包含 id 屬性。咱們能夠經過 HTMLElement 接口中的 id 屬性得到這個元素的標識符,而經過 Element 接口中的 getAttibute 方法傳入參數 "id" 一樣能夠得到標識符。
雖然這兩種方式能夠得到相同的值,可是卻有着天壤之別。從規範層面上看,getAttribute 方法所屬的 DOM (Core) 規範定義了訪問和操做文檔對象的一套對象和接口,這其中包含了對 HTML 及 XML 的解析及操做;HTMLElement 接口中 id 屬性所屬的 DOM (HTML) 規範爲 DOM (Core) 的擴展,描述了 HTML 及 XHTML 的對象的細節。而從 HTML 文檔代碼的層面上看,一個元素的標記中的 HTML 屬性(attribute)與其對應的 DOM 對象的屬性(property)也是徹底不一樣的兩個概念。htm
關於 getAttribute 與 setAttribute 的詳細信息,請參考 DOM (Core) Level 1 及 Level 2 中的內容。
關於 HTML DOM 對象 的詳細信息,請參考 DOM (HTML) Document Object Model HTML,特別是 1.6.1. Property Attributes 中的內容。
IE6 IE7 IE8(Q) 混淆了 DOM 對象的屬性(property)及 HTML 標籤屬性(attribute)這兩個概念。其對於 getAttribute 及 setAttribute 方法的實現與 HTML DOM 對象的屬性的 getter 與 setter 操做等價,這個錯誤的實現方式致使了一系列的兼容性問題。而在 IE8(S) 中,致使的大多數兼容性問題已不存在,可是仍然能夠經過 "Element.PropertyName" 訪問到這個 HTML 元素的自定義屬性。
IE6 IE7 IE8(Q) | |
---|---|
IE8(S) |
在 MSDN 中的一篇名爲 "Attribute Differences in Internet Explorer 8" 的一篇官方文檔中提到,因爲 DOM 屬性(文中稱做 "DOM attribute" )一般與其所對應的 HTML 屬性(文中稱做 "content attribute" )同名,所以經常被認爲這兩個 "屬性" 的值是相同的。例如 DOM 中 BODY 對象的 background 屬性(property)看上去彷佛與 HTML 文檔中 BODY 元素的 background 屬性(attribute)的值相同。在早期版本的 IE 瀏覽器中, "property" 的值與分配給元素 "attribute" 的值相同,而同時 "property" 的值也以元素 "attribute" 的值爲基礎,所以,這兩個值之間在術語上已變得含糊不清。
對於絕大多數 "property" 與 "attribute" 在名稱及值類型上是統一的。但也有一些特例,
接下來經過代碼分析 IE 因爲混淆 DOM 對象的屬性(property)及 HTML 屬性(attribute)致使的常見的兼容性問題。
代碼 custom_attributes_and_properties.html:
<!DOCTYPE html> <html> <head> <script> function $(id) { return document.getElementById(id); } window.onload = function () { var d1 = $("d1"); d1.setAttribute("setAttr2", "value2"); d1.customProperty3 = "value3"; d1.id = "d2"; var dn = document.createElement("div"); var str = []; $("info2").value = $("cont").innerHTML; for (var i in d1) { if (!(i in dn)) { str.push(i + ":" + d1[i] + "<br />"); } } $("info1").innerHTML = (str.length == 0) ? "N/A" : str.join(""); } </script> </head> <body style="font:20px Arial;"> <div id="cont"><div id="d1" customAttr1="value1">'d1': HTMLDivElement 1</div></div> <br /> <h1>Extra property:</h1> <div id="info1"></div> <br /> <h1>HTML code:</h1> <textarea id="info2" cols="200" style="font:16px Arial;"></textarea> </body> </html>
上面代碼中,DIV 元素【d1】在其 HTML 標籤上出現了 1 個自定義屬性(attribute)——customAttr1。頁面加載完成後,使用 setAttribute 方法爲【d1】的標籤上設置了 setAttr2 屬性,爲【d1】對應的 HTMLDivElement 對象設置了 customProperty3 屬性,爲【d1】對應的對象設置了 id 屬性。
而後,經過 "for..in" 遍歷【d1】對應的 HTMLDivElement 對象內的屬性(property),爲了方便觀察,特意經過與一個新建立的 HTMLDivElement 對象作比較,過濾了二者重複的對象屬性,只顯示出與新建立的 HTMLDivElement 對象存在差別的屬性及屬性值。
這段代碼在不一樣的瀏覽器環境中的表現:
IE6 IE7 IE8 | Firefox Chrome Safari Opera | |
---|---|---|
Extra property | customAttr1:value1 setAttr2:value2 customProperty3:value3 |
customProperty3:value3 |
HTML code | <DIV id="d2" customAttr1="value1" setAttr2="value2"customProperty3="value3">'d1': HTMLDivElement 1</DIV> | <div id="d2" customattr1="value1" setattr2="value2">'d1': HTMLDivElement 1</div> |
在解析 HTML 文檔時,全部版本的 IE 中自定義的 HTML 標籤屬性成爲了該元素對應的 DOM 對象中的屬性,這使得能夠經過 "d1.customAttr1" 或者 "d1["customAttr1"]" 獲取的到這個自定義 HTML 屬性的值。在使用 setAttribute 方法爲元素的標籤設置自定義 HTML 屬性後,該元素對應的 DOM 對象上也會自動綁定上這個屬性名及其屬性值。同時,在爲元素對應的 DOM 對象設置了一個屬性後,其在 HTML 文檔中對應的元素的 HTML 標籤上也會出現這個自定義的屬性名及其屬性值。
而在 Firefox Chrome Safari Opera 中,能夠看到元素的 HTML 標籤屬性(attribute)和元素對應的 DOM 對象屬性(property)是清晰地被分開的。
根據規範,HTMLDivElement 接口繼承自 HTMLElement,實現了 HTMLDivElement 接口的對象(即 HTML 文檔中 DIV 元素所對應的 DOM 對象)擁有 HTMLElement 接口中定義的全部屬性(id、title、lang、dir、className 屬性)及方法,以及其私有的 align 屬性。【d1】最初在其 HTML 標籤代碼中有 id 及 customAttr1 兩個屬性,根據 DOM 規範,DIV 元素的 id 屬性是會將其暴露給其對應的 HTMLDivElement 對象的 id 屬性的,此時這兩個層面的 id 屬性會保持同步,即瀏覽器在解析 HTML 文檔時,會將【d1】標籤內的 id 屬性及其值綁定至【d1】所對應的 DOM 對象上;同時當設置其 DOM 對象的 id 屬性時,【d1】的 HTML 標籤上的 id 屬性也會隨着發生變化。
customAttr1 爲自定義屬性,DOM 規範中全部的實現接口中均不包含這個屬性。這時因爲不存在 DOM 規範中所描述的綁定關係,瀏覽器會認爲 customAttr1 屬性僅爲這個 DOM 對象上的一個普通屬性,和其對應的 HTML 文檔中的標籤屬性沒有任何關係。因此爲 DOM 對象設置一個自定義屬性不會對 HTML 文檔產生任何效果。
setAttr2 屬性一樣爲自定義屬性,一樣不存在 DOM 規範中所描述的綁定關係,使用 setAttribute 方法設置的 setAttr2 屬性僅僅是爲【d1】的 HTML 標籤上設置了一個自定義的 HTML 屬性,這個操做隻影響 HTML 文檔內容,不該對 DOM 對象自身產生做用。
本例中,能夠認爲 IE 沿用了 W3C 規範中明確棄用的作法,將 HTML 規範中未定義的自定義屬性也「暴露」給了對應的 DOM 對象,使得 HTML 元素的自定義屬性與對應的 DOM 對象的自定義屬性也會像規定中定義了綁定關係的那些標準屬性同樣能夠保持着一種同步關係。
代碼 attribute_and_property_value.html:
<!DOCTYPE html> <html> <head> <style> input, textarea { font:12px consolas; width:400px; } </style> <script> function $(id) { return document.getElementById(id); } function addInputEvent(elem, handler, useCapture) { elem.addEventListener ? elem.addEventListener("input", handler, false) : elem.attachEvent("onpropertychange", handler); } window.onload = function () { var psw = $("psw"), cont = $("cont"), ta = $("ta"), txt; var inputing = function () { txt = cont.innerHTML + '/npsw.value:' + psw.value + '/npsw.getAttribute("value"):' + psw.getAttribute("value"); ta.value = txt; } addInputEvent(psw, inputing); inputing(); } </script> </head> <body> <div id="cont"><input id="psw" type="text" value="old value" /></div> <textarea id="ta" style="height:100px;"></textarea> </body> </html>
上面代碼中 INPUT 文本框的 value 初始值爲 "old value",當在文本框內輸入字符時,會在其下方實時顯示 INPUT 文本框的 HTML 標籤代碼,以及其 DOM 對象的 value 屬性值和 getAttribute("value") 獲得的值。
這段代碼在不一樣的瀏覽器環境中的表現:
IE6 IE7 IE8 | Firefox Chrome Safari Opera | |
---|---|---|
初始狀態:"old value" | <INPUT id=psw value="old value" type=text> psw.value:old value psw.getAttribute("value"):old value |
<input id="psw" type="text" value="old value"> psw.value:old value psw.getAttribute("value"):old value |
清空文本框:"" | <INPUT id=psw type=text > psw.value: psw.getAttribute("value"):null |
<input id="psw" type="text" value="old value"> psw.value: psw.getAttribute("value"):old value |
輸入新值:"12345" | <INPUT id=psw value=12345 type=text> psw.value:12345 psw.getAttribute("value"):12345 |
<input id="psw" type="text" value="old value"> psw.value:12345 psw.getAttribute("value"):old value |
根據 DOM Level 2 HTML 規範中的描述,當 INPUT 元素 type 屬性爲 "text"、"file" 或 "password" 時,其對應的 HTMLInputElement 對象的 value 屬性表明了這個控件 "當前值",修改這個屬性會改變控件的 "當前值",可是並不會改變其 HTML 標籤上的 value 屬性。
根據 HTML4.01 規範中的描述,一個 INPUT 元素 HTML 標籤上的 value 屬性指定了這個控件的 "初始值"。最初的 "當前值" 會採用 "初始值"。
即,對於本例中的 INPUT 元素,其 HTML 標籤內的 value 屬性爲 "old value",則初始值爲 "old value",而最初的 "當前值" 也爲 "old value"。在用戶改變 INPUT 文本框的內容時,"當前值" 發生變化,此時這個 INPUT 文本框對應的 DOM 對象的 value 屬性也隨着 "當前值" 而變化,但並不會影響到文本框的 HTML 標籤上的 value 屬性。
能夠看到在 Firefox Chrome Safari Opera 中,在 INPUT 元素的輸入新的 "當前值" 盡能夠改變文本框對應的 DOM 對象的 value 屬性。而在 IE 中,HTML 標籤的 value 屬性也會跟隨 "當前值" 的變化而變化。
因此,只有在 IE 中能夠經過 getAttribute("value") 能夠獲取到 INPUT 文本框內的實時內容。
代碼 attribute_and_property_class.html:
<!DOCTYPE html> <html> <head> <style> div { width:300px; height:100px; background:#eee; font:12px Arial; } .d1 { background:pink; font:18px Arial; } .d2 { background:gold; font:18px Arial; } .d3 { background:plum; font:18px Arial; } </style> <script> function getClass(obj) { obj.innerHTML = '.className=' + obj.className + '<br>.getAttribute("class")=' + obj.getAttribute("class") + '<br>.getAttribute("className")=' + obj.getAttribute("className"); } window.onload = function () { var d1 = document.getElementById("d1"); var d2 = document.getElementById("d2"); var d3 = document.getElementById("d3"); d1.className = "d1"; d2.setAttribute("class", "d2"); d3.setAttribute("className", "d3"); getClass(d1); getClass(d2); getClass(d3); } </script> </head> <body> <div id="d1">d1</div> <div id="d2">d2</div> <div id="d3">d3</div> </body> </html>
上面代碼中分別使用 obj.className = "XXX"、obj.setAttribute("class", "XXX")、obj.setAttribute("className", "XXX") 試圖爲【d1】、【d2】、【d3】設置一個 CSS 的 class。而後對於這三個 DIV 元素再使用 obj.className、obj.getAttribute("class")、obj.getAttribute("className") 獲得它們的返回值。
這段代碼在不一樣的瀏覽器環境中的表現:
IE6 IE7 IE8(Q) | IE8(S) Firefox Chrome Safari Opera |
---|---|
能夠看到,在 IE8(S) Firefox Chrome Safari Opera 中,結果符合規範。而在 IE6 IE7 IE8(Q) 中,沒法經過 setAttribute 和 getAttribute 方法經過傳入 class 參數作爲屬性名來設置及獲取元素的 class 屬性,而必須經過傳入 className 參數。在其餘瀏覽器中,傳入 className 參數僅僅是爲元素的 HTML 標籤設置與獲取一個自定義的 className 屬性的值。
代碼 attribute_and_property_style.html:
<!DOCTYPE html> <html> <head> <style> * { font-family:Arial; } div { width:400px; height:100px; background:#eee; font-size:12px; margin-bottom:1px; } </style> <script> function getStyle(obj) { obj.innerHTML = '.style.cssText=' + (obj.style.cssText).toLowerCase() + '<br>.getAttribute("style")=' + ("" + obj.getAttribute("style")).toLowerCase(); } window.onload = function () { var d1 = document.getElementById("d1"); var d2 = document.getElementById("d2"); var styleText = "background-color:rgb(51, 204, 204); font-size:16px"; d1.style.cssText = styleText; d2.setAttribute("style", styleText); getStyle(d1); getStyle(d2); } </script> </head> <body> <div id="d1">d1</div> <div id="d2">d2</div> </body> </html>
上面代碼中分別使用 obj.style.cssText = "XXX"、obj.setAttribute("style", "XXX") 試圖爲【d1】、【d2】設置一個內聯樣式。而後對於這兩個 DIV 元素再使用 obj.style.cssText、obj.getAttribute("style") 獲得它們的返回值。
這段代碼在不一樣的瀏覽器環境中的表現:
IE6 IE7 IE8(Q) | IE8(S) Firefox Chrome Safari Opera |
---|---|
能夠看到,在 IE8(S) Firefox Chrome Safari Opera 中,結果符合規範。而在 IE6 IE7 IE8(Q) 中,沒法經過 setAttribute 和 getAttribute 方法經過傳入 style 參數作爲屬性名來設置及獲取元素的 style 屬性中的內聯樣式,getAttribute("style") 返回的是一個 CSSStyleDeclaration 對象。
代碼 attribute_and_property_event.html:
<!DOCTYPE html> <html> <head> <style> * { font:12px Consolas; } button, textarea { width:700px; } </style> <script> function $(id) { return document.getElementById(id); } function getOnclick(index) { $("d" + index).value = $("cont" + index).innerHTML; } window.onload = function () { var b1 = $("b1"); var b2 = $("b2"); var cont1 = $("cont1"); var cont2 = $("cont2"); var s1 = $("s1"); var s2 = $("s2"); var funcStr1 = "$('s1').innerHTML='set string<br>get '+typeof this.getAttribute('onmouseover')"; var funcStr2 = "$('s2').innerHTML='set function<br>get '+typeof this.getAttribute('onmouseover')"; b1.setAttribute("onclick", funcStr1); b2.setAttribute("onclick", new Function(funcStr2)); b1.click(); b2.click(); } </script> </head> <body> <div id="cont1"><button id="b1" type="button" onmouseover="">"$('s1').innerHTML='trigger'"</button></div><span id="s1">N/A</span><br /> <br /><br /> <div id="cont2"><button id="b2" type="button" onmouseover="">function () { $('s2').innerHTML='trigger' }</button></div><span id="s2">N/A</span><br /> </body> </html>
上面代碼中分別使用 obj.setAttribute("onclick", "[code]"、obj.setAttribute("onclick", function () { [code] }) 試圖爲【b1】、【b2】設置一個內聯事件。而後觸發這兩個 BUTTON 元素的 click 事件。
這段代碼在不一樣的瀏覽器環境中的表現:
IE6 IE7 IE8(Q) | IE8(S) Firefox Chrome Safari Opera | |
---|---|---|
b1.setAttribute("onclick", "$('s1').innerHTML='trigger'"); | N/A | set string get string |
b2.setAttribute("onclick", function () { $('s2').innerHTML='trigger' }); | set function get function |
N/A |
能夠看到,在 IE8(S) Firefox Chrome Safari Opera 中,結果符合規範。而在 IE6 IE7 IE8(Q) 中,沒法經過 setAttribute 方法傳入一段代碼字符串設置一個元素的內聯事件,而必須傳入一個 function 類型的對象;獲取一個已有的內聯事件的屬性值也是 function 類型,而不是規範中的字符串類型。
代碼 attribute_and_property_DHTML.html:
<!DOCTYPE html> <html> <head> <style> * { font-family:Arial; } div { width:100px; height:100px; background:#eee; font-size:12px; } textarea { width:600px; } </style> <script> function getStyle(obj) { obj.innerHTML = '.style.cssText=' + (obj.style.cssText).toLowerCase() + '<br>.getAttribute("style")=' + ("" + obj.getAttribute("style")).toLowerCase(); } window.onload = function () { var d = document.getElementById("d"); var cont= document.getElementById("cont"); var info= document.getElementById("info"); var s = 'd.getAttribute("offsetHeight"): '; s += d.getAttribute("offsetHeight") + "/n"; d.setAttribute("innerHTML", "other text"); info.value = s + cont.innerHTML; } </script> </head> <body> <div id="cont"><div id="d">text text text text text text text</div></div> <textarea id="info"></textarea> </body> </html>
、
這段代碼在不一樣的瀏覽器環境中的表現:
IE6 IE7 IE8(Q) | IE8(S) Firefox Chrome Safari Opera | |
---|---|---|
d.getAttribute("offsetHeight") | 100 | null |
d.setAttribute("innerHTML", "other text"); | <DIV id=d>other text</DIV> | <div id="d" innerhtml="other text">text text text text text text text</div> |
能夠看到,在 IE8(S) Firefox Chrome Safari Opera 中,因爲【d】的 HTML 標籤中沒有 "offsetHeight" 屬性,因此 getAttribute("offsetHeight") 根據規範要求返回了 null;setAttribute("innerHTML", "other text") 則爲【d】的 HTML 標籤上設置了一個 innerHTML 屬性,值爲 other text。
而在 IE6 IE7 IE8(Q) 中,"offsetHeight" 屬性返回了【d】元素對應的 DOM 對象中的 offsetHeight 屬性的值;setAttribute("innerHTML", "other text") 則至關於調用了 d.innerHTML = "other text",因此【d】的 HTML 標籤上並無出現 innerHTML 屬性及其值。
經過上述幾個測試樣例,能夠看到 IE6 IE7 IE8(Q) 中,Element.getAttribute("attrName") 與 Element.attrName 等效,Element.setAttribute("attrName, "XXX") 與 Element.attrName = "XXX" 等效。IE8(S) 修復了由 getAttribute、setAttribute 方法所帶來的大多數兼容性問題,但並無改變 IE 自己對於 DOM 對象的屬性(property)及 HTML 標籤屬性(attribute)相互混淆的錯誤設計,對於表單元素的 value 屬性以及自定義 HTML 屬性仍然保持與 IE6 IE7 相同的現象。
結合這些測試結果,列表以下:
執行的代碼 | 在 IE6 IE7 IE8(Q) 中實際等效代碼 | 在 IE8(S) 中實際等效代碼 | 在 Firefox Chrome Safari Opera 中實際等效代碼 |
---|---|---|---|
d1.getAttribute("class") | d1["class"] | d1.getAttribute("class") | |
d1.setAttribute("class", "XXX") | d1["class"] = "XXX" | d1.setAttribute("class") | |
d1.getAttribute("className") | d1.className | d1.getAttribute("className") | |
d1.setAttribute("className", "XXX") | d1.className = "XXX" | d1.setAttribute("className", "XXX") | |
d1.getAttribute("style") | d1.style | d1.getAttribute("style") | |
d1.setAttribute("style", "XXX") | 操做無效 | d1.setAttribute("style", "XXX") | |
d1.getAttribute("onclick") | d1.onclick | d1.getAttribute("onclick") | |
d1.setAttribute("onclick", "XXX") | d1.onclick = "XXX" | d1.setAttribute("onclick", "XXX") | |
d1.setAttribute("innerHTML", "XXX") | d1.innerHTML = "XXX" | d1.setAttribute("innerHTML", "XXX") | |
d1.getAttribute("offsetHeight") | d1.offsetHeight | d1.getAttribute("offsetHeight") | |
d1.setAttribute("value", "XXX") | d1.value = "XXX" | d1.setAttribute("value", "XXX") | |
d1.getAttribute("id2") | d1.id2 | d1.getAttribute("id2") |