之前看到
jQuery 1.6.1上場救援,不用改寫attr()囉這篇文章時,讓我很疑惑 Attribute 與 Property 到底是有什麼不同,在字典上查出來的結果都是
屬性,爬了一些文章後找到一篇不錯的解釋文。
轉載自:
屬性與特性
在進入瀏覽器作為客戶端之後,屬性(Attribute)與特性(Property)這兩個名詞就不斷交相出現,到目前還沒正式解釋它們的意義。
其實在正式進入瀏覽器作為客戶端前,對於JavaScript物件本身帶有的名稱,這邊的文件都用
特性這個名詞,代表以某個JavaScript物件作為名稱空間的名稱。例如:
var obj = {
x : 10,
y : 20
};
以上文件都稱,物件obj擁有特性x與y,特性x的值為10,特性y的值為20。
HTML本身可以擁有屬性。例如:
<input name="user" value="guest">
文件中會稱,<input>標籤擁有
屬性name與value,屬性值各為user與guest。
瀏覽器會剖析HTML,為每個標籤建立對應的DOM物件,完成剖析後,對於HTML的所有屬性(無論標籤上是否有撰寫),DOM物件上會建立對應的特性,通常屬性名稱是什麼,特性名稱也會是什麼,如果標籤上有設定某個屬性,則屬性值為何,特性值也就為何,如果標籤上沒有設置屬性,則DOM物件上的特性會有預設值。
例如上例中,<input>對應的DOM元素上,name特性與value特性值分別是user與guest。你可以如下分別取得(假設是頁面中第一個<input>標籤):
var input = document.getElementsByName('user')[0];
var name = input.name;
var value = input.value;
像這時,DOM元素上的name、value特性,也可以稱之為name與value屬性。也就是說,屬性這個詞,可用來表示HTML中的屬性,也可用來表示DOM中相對應的特性。對於HTML中沒有設定的標籤屬性,DOM上也會有對應的特性(屬性),不過都是預設值,例如,上面的<input>標籤並沒有設置type屬性,但DOM物件上對應的特性(屬性),其值為"text"。
不過,
HTML的屬性名稱未必與DOM物件的特性(屬性)名稱相對應。例如class就是一個例子,因為class在JavaScript中是關鍵字,在DOM上要取得HTML的class屬性對應名稱必須使用
className,<label>的for屬性,因為for是關鍵字,而必須使用
htmlFor特性來取得。例如:
<img id="logo" src="images/caterpillar.jpg" class="logo" title="Caterpillar's Logo"/>
若要以JavaScript取得HTML的class屬性值,則必須:
var className = document.getElementById('logo').className;
透過JavaScript特性存取方式取得HTML屬性的對應值,也未必是HTML屬性中真正設定的值。例如,透過JavaScript取得<img>的src,結果是絕對URL,即使屬性中設定的是相對URL。
瀏覽器在剖析完HTML後,對於HTML中有設置的屬性,其實會在DOM物件上建立attributes特性。你可以如下顯示attributes的元素值,每個元素的型態是
Attr:
var attributes = document.getElementById('logo').attributes;
for(var i = 0; i < attributes.length; i++) {
var attrName = attributes[i].nodeName;
var attrValue = attributes[i].nodeValue;
...
}
以物件結構來表示的話:
{
attributes : {
'0' : {nodeName : 'id', nodeValue : 'logo', ...},
'1' : {nodeName : 'src', nodeValue : 'images/src', ...},
'2' : {nodeName : 'class', nodeValue : 'logo', ...},
'3' : {nodeName : 'title', nodeValue : 'Caterpillar\’s logo', ...},
length : 4
...
},
id : 'logo',
src : 'http://caterpillar.onlyfun.net/images/caterpillar.jpg',
className : 'logo',
title : 'Caterpillar\'s logo',
…
}
attributes上的特性值,是HTML上真正設定的屬性與值。
在文件剖析完畢後,DOM物件上的屬性(特性)與attributes上的特性是對應的。
注意,上面是以物件結構來示意,並不是指真正的型態就是上面所表示的。attributes的型態會是
NamedNodeMap ,而每個索引元素的型態會是
Attr(如果你手邊有個JavaScript Debugger的話,可以很方便地觀察這些東西)。
你可以使用DOM物件的getAttribute()來取得
attributes中的屬性,使用setAttribute()設定
attributes中的屬性(同時亦會改變DOM對應的特性),使用removeAttribute()來移除
attributes屬性。
移除屬性是指移除attributes上對應的特性值,而非移除DOM物件上對應的特性(屬性)值,DOM物件上對應的特性(屬性)值在使用removeAttribute()後,只是回到預設值,而不是直接將特性移除,沒有任何操作可以將DOM上對應屬性的特性移除。如果HTML上沒有設置該屬性,則使用getAttribute()指定該屬性會取得null,但並不表示DOM上沒有對應屬性的特性,而是該特性值會是預設值。使用setAttribute()可以在attributes中設定屬性,相對應的DOM特性值也會改變。
例如,以下的程式,只會將attributes的中src對應的特性移除,不會移除DOM上src特性(屬性),DOM上src只是回到''的預設值。
var img = document.getElementById('logo');
img.removeAttribute('src');
// img.src 的值是 '',不是undefined
// img.attributes['src'] 是 undefined
如果你直接改變DOM上的特性(屬性),attributes中對應的屬性並不會有變化。例如:
<input id="user" value="guest">
使用以上的程式:
document.getElementById('user').value = 'Justin';
var user1 = document.getElementById('user').value; // 值是'Justin'
var user2 = document.getElementById('user').getAttribute('value'); // 值是'guest'
如果你要同時改變attribues上的屬性與DOM上的特性(屬性),則要使用setAttribute()。例如:
document.getElementById('user').setAttribute('value', 'Justin');
var user1 = document.getElementById('user').value; // 值'Justin'
var user2 = document.getElementById('user').getAttribute('value'); // 值'Justin'
其他參考資訊:
property和attribute的区别
JavaScript property 、 DOM property 、 HTML attribute
翻譯名詞:attribute、property