attribute和property這兩個單詞,都有屬性的意思,attribute有屬性、特質的意思,property則有性質,性能的意思。
首先需要明確的是,在規范中,讀取和設置attribute的方法是getAttribute/setAttribute/removeAttribute,比如box.setAttribute('somekey','somevalue')
而想要訪問元素的property,則需要用.(點)的方法,比如,box.somekey,下面先說attribute:
<div id="box" test1="test2" game1="gamesomeabc">box content</div>
每個DOM元素都有一個對應的attributes屬性來存放所有的attribute節點,attributes是一個類數組的容器,說得准確點就是NameNodeMap,總之就是一個類似數組但又和數組不太一樣的容器。attributes的每個數字索引以名值對(name=”value”)的形式存放了一個attribute節點。如下圖:
var box = document.getElementById('box');
box.getAttribute('test1') // test2
box.attribute[0].value // box
box.attribute[3].value // ttt
並且,attribute是動態變化的,如下圖:
而property就是一個屬性,如果把DOM元素看成是一個普通的Object對象,那么property就是一個以名值對(name=”value”)的形式存放在Object中的屬性。要添加和刪除property也簡單多了,和普通的對象沒啥分別:
之所以attribute和property容易混倄在一起的原因是,很多attribute節點還有一個相對應的property屬性,比如上面的div元素的id和class既是attribute,也有對應的property,不管使用哪種方法都可以訪問和修改。但是對於自定義的attribute,就沒事了。
box.getAttribute('id') // box box.id // box box.newkey // undefined box.getAttribute('newkey') //newvalue
所以說:規范中,瀏覽器會默認的將一些attribute與property共用,比如id,class,style等,我們可以通過getAttribute()或者點的方式進行獲取,而如果setAttribute的屬性是瀏覽器中不共用的,我們就只能通過getAttribute進行獲取。
但是注意:這里是指規范,而IE6、IE7是不規范的。而這里就是個大坑。
box.setAttribute('test1','abc'); alert(box.test1); //IE6/IE7 彈出abc IE8+彈出undefined
雖然說,有些屬性(id,class,title)是attribute和property共用的,但是他們也會出現不一致的情況。
<input type="radio" checked="checked" id="someRadio"> var someRadio = document.getElementById('someRadio'); alert(someRadio.checked + '--' + someRadio.getAttribute('checked')); //IE6/7 彈出 true--true IE8+ true--checked
由此可見,attribute很顯然,就訪問的元素的HTML標簽下的值,而property訪問的是DOM元素引用(相當於一個對象)的值。
而IE6/7是不去分attribute和property的,這就給兼容的時候帶來了很大的問題,我們來看看jQuery對於attribute的兼容方式(大概思路):
var div = document.createElement('div'); div.setAttribute('className', 't'); console.log(div.className !== 't'); // IE6/7 打印出false chrome打印出false
jQuery這里先用setAttribute來設置className為t,然后用div.className來取值,按照規范,這里是取不到的,所以在IE8+瀏覽器,這里返回false,但是IE6/7對attribute和property不進行區分,所以導致div.className也為t,返回true,這段代碼在support模塊中,用處是判斷setAttribute和getAttribute是否安全(是否可用)。
如果不安全,在設置attribute是就要用到別的方法:這里用到了getAttributeNode和setAttribute方法,雖然還是無法將attribute和property分開,但是解決了大部分IE67的問題。
function setIE67Attribute(box, key, value) { var attributeNode = document.createAttribute(key); box.setAttributeNode(attributeNode); attributeNode.value = value; } function getIE67Attribute(box, key) { return box.getAttributeNode(key).value; } setIE67Attribute(box, 'customkey', 'customvalue'); alert(getIE67Attribute(box,'customkey')); //customvalue alert(box.customkey);//customvalue box.abc = 'def'; alert(getIE67Attribute(box,'abc'));//abc alert(box.getAttribute('abc'));//abc
到這里,attribute這個東西的兼容性還有很多,坑多的是,詳情移步jQuery源代碼吧。請看這里:jQuery.attributes源碼分析(attr/prop/val/class)
關於attribute和property的兼容性:attribute和property兼容性分析
參考:
http://www.jb51.net/article/50686.htm
http://www.liyao.name/2013/09/differences-between-property-and-attribute-in-javascript.html
http://www.cnblogs.com/rubylouvre/archive/2010/03/07/1680403.html
http://ju.outofmemory.cn/entry/36093
http://www.cnblogs.com/aaronjs/p/3387906.html
http://www.jb51.net/article/29263.htm
http://www.cnblogs.com/wangfupeng1988/p/3631853.html
http://www.cnblogs.com/wangfupeng1988/p/3639330.html
http://www.cnblogs.com/wangfupeng1988/p/3626300.html