Javascript中的attribute和property分析


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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM