作者:大搜車前端團隊部落格
網址:http://f2e.souche.com/blog/domde-attributehe-property/
property和attribute的漢語翻譯幾乎相同,都有“屬性”的意義(這裡姑且稱attribute為“特性”,以方便區分),而他們的取值也經常相同,但有時又會踩坑,發現二者會不相等,不同步。
0.奇葩的IE
本文開始之前不得不提一下萬惡之源IE,在IE<9中,瀏覽器會把所有的property和attribute強制對映,即property = attribute. (class特殊:className = class)。正因為IE<9中的這種對映誤導了很多人以為二者完全相同。
1. Property
每個DOM節點都是一個object物件,它可以像其他的js Object一樣具有自己的property和method,所以property的值可以是任何資料型別,大小寫敏感,原則上property應該僅供js操作,不會出現在html中(預設屬性除外:id/src/href/className/dir/title/lang等),和其他js object一樣,自定義的property也會出現在object的for…in遍歷中。
eg.
var list=[];
for(var key in document.body) {
list.push(key)
}
console.log(list.join(‘\n’));
2. Attribute
attribute出現在dom中,js提供了getAttribute/setAttribute等方法來獲取和改變它的值,attribute的值只能是字串且大小寫不敏感,最後作用於html中,可以影響innerHTML獲取的值。可以透過訪問dom節點的attributes屬性來獲取改節點的所有的attribute。(在IE<9中,attribute獲取和改變的實際上是property。)
3.自定義的Property與Attribute不同步,不相等
html:
js:
var test = document.getElementById(‘test’);
test.self = ‘selfProperty’;
console.log(test.self) => ‘selfProperty’
test.getAttribute(‘self’) => null
conclusion:自定義的property與自定義的attribute無同步關係
4.非自定義的DOM property與 attributes 是有條件同步的
非自定義的屬性(id/src/href/name/value等),透過setAttribute修改其特性值可以同步作用到property上,而透過.property修改屬性值有的(value)時候不會同步到attribute上,即不會反應到html上(除以下幾種情況,非自定義屬性在二者之間是同步的)。
- 非自定義屬性(id/src/href/name/value等)未顯式定義在dom中才會時,初始的property與attribute不同
html:
初始值property: testvalue.value => “”
初始值attribute: testvalue.getAttribute(‘value’) => null
- input:value/checked的單向同步關係透過setAttribute改變input的value/checked都會同步到property中,但是,一旦改變他們的property值,就打破同步機制
html:
property: testvalue.value => ‘sync’
attribute: testvalue.getAttribute(‘value’) => ‘sync’
testvalue.setAttribute(‘value’,’abc’) => ‘abc’
則屬性會同步: testvalue.value => ‘abc’
testvalue.value = ‘ddd’;
則同步機制失效: testvalue.getAttribute(‘value’) => ‘abc’
- 同步不是複製,同步機制依舊,值不同(src/href)透過getAttribute獲取的是href/src的實際值,而點號(property)獲取的是完整的url。
html: a(id=”testHr” href=”/test/”)
property: testHr.href=”/blog/” => ‘http://f2e.souche.com/blog/’
attribute: testHr.getAttribute(‘href’) => ‘/blog/’
- 非直接對映的同步,雖然同步了,但是同步後的屬性名字不同,或者取值方式不同:class/data-XX/styleclass對映成className
data-XXX對映到 dataset.XXX,透過JQuery的attr,prop訪問時候不同步。
style屬性不接受字串型賦值,只能透過style.XXX
html:
testvalue.getAttribute(‘class’) <=>testvalue.className
testvalue.setAttribute(‘style’,’color:red’) <=> testvalue.style.color
testvalue.getAttribute(‘data-id’)<=> testvalue.dataset.id
小結
property與attribute都是dom的核心功能,鑒於有的屬性上會出現單項同步的情況似乎attribute貌似更保險一點,以下是二者的關係表: