2011-07-11 14:49

[轉載] 屬性(Attribute)與特性(Property)

之前看到jQuery 1.6.1上場救援,不用改寫attr()囉這篇文章時,讓我很疑惑 Attribute 與 Property 到底是有什麼不同,在字典上查出來的結果都是屬性,爬了一些文章後找到一篇不錯的解釋文。


轉載自:屬性與特性

在進入瀏覽器作為客戶端之後,屬性(Attribute)與特性(Property)這兩個名詞就不斷交相出現,到目前還沒正式解釋它們的意義。

其實在正式進入瀏覽器作為客戶端前,對於JavaScript物件本身帶有的名稱,這邊的文件都用特性這個名詞,代表以某個JavaScript物件作為名稱空間的名稱。例如:
  1. var obj = { 
  2.    x : 10, 
  3.    y : 20 
  4. }; 

以上文件都稱,物件obj擁有特性x與y,特性x的值為10,特性y的值為20。

HTML本身可以擁有屬性。例如:
  1. <input name="user" value="guest"> 

文件中會稱,<input>標籤擁有屬性name與value,屬性值各為user與guest。

瀏覽器會剖析HTML,為每個標籤建立對應的DOM物件,完成剖析後,對於HTML的所有屬性(無論標籤上是否有撰寫),DOM物件上會建立對應的特性,通常屬性名稱是什麼,特性名稱也會是什麼,如果標籤上有設定某個屬性,則屬性值為何,特性值也就為何,如果標籤上沒有設置屬性,則DOM物件上的特性會有預設值

例如上例中,<input>對應的DOM元素上,name特性與value特性值分別是user與guest。你可以如下分別取得(假設是頁面中第一個<input>標籤):
  1. var input = document.getElementsByName('user')[0]; 
  2. var name = input.name; 
  3. 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特性來取得。例如:
  1. <img id="logo" src="images/caterpillar.jpg" class="logo" title="Caterpillar's Logo"/> 


若要以JavaScript取得HTML的class屬性值,則必須:
  1. var className = document.getElementById('logo').className; 

透過JavaScript特性存取方式取得HTML屬性的對應值,也未必是HTML屬性中真正設定的值。例如,透過JavaScript取得<img>的src,結果是絕對URL,即使屬性中設定的是相對URL。

瀏覽器在剖析完HTML後,對於HTML中有設置的屬性,其實會在DOM物件上建立attributes特性。你可以如下顯示attributes的元素值,每個元素的型態是Attr
  1. var attributes = document.getElementById('logo').attributes; 
  2. for(var i = 0; i < attributes.length; i++) { 
  3.    var attrName = attributes[i].nodeName; 
  4.    var attrValue = attributes[i].nodeValue; 
  5.    ... 
  6. } 

以物件結構來表示的話:
  1. { 
  2.    attributes : { 
  3.        '0' : {nodeName : 'id', nodeValue : 'logo', ...}, 
  4.        '1' : {nodeName : 'src', nodeValue : 'images/src', ...}, 
  5.        '2' : {nodeName : 'class', nodeValue : 'logo', ...}, 
  6.        '3' : {nodeName : 'title', nodeValue : 'Caterpillar\’s logo', ...}, 
  7.        length : 4 
  8.        ... 
  9.    }, 
  10.    id : 'logo', 
  11.    src : 'http://caterpillar.onlyfun.net/images/caterpillar.jpg', 
  12.    className : 'logo', 
  13.    title : 'Caterpillar\'s logo', 
  14.    … 
  15. } 

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只是回到''的預設值。
  1. var img = document.getElementById('logo'); 
  2. img.removeAttribute('src'); 
  3. // img.src 的值是 '',不是undefined 
  4. // img.attributes['src'] 是 undefined 

如果你直接改變DOM上的特性(屬性),attributes中對應的屬性並不會有變化。例如:
  1. <input id="user" value="guest"> 

使用以上的程式:
  1. document.getElementById('user').value = 'Justin'; 
  2. var user1 = document.getElementById('user').value; // 值是'Justin' 
  3. var user2 = document.getElementById('user').getAttribute('value'); // 值是'guest' 

如果你要同時改變attribues上的屬性與DOM上的特性(屬性),則要使用setAttribute()。例如:
  1. document.getElementById('user').setAttribute('value', 'Justin'); 
  2. var user1 = document.getElementById('user').value; // 值'Justin' 
  3. var user2 = document.getElementById('user').getAttribute('value'); // 值'Justin' 


其他參考資訊:
property和attribute的区别
JavaScript property 、 DOM property 、 HTML attribute
翻譯名詞:attribute、property

0 回應: