轉載自:屬性與特性
在進入瀏覽器作為客戶端之後,屬性(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
0 回應:
張貼留言