DOM元素的屬性(property)和特性(attribute)

從jQuery的prop()attr()方法說開去

jQuery中有兩個獲取DOM元素屬性的方法:prop()attr(),看似能夠互相替換,但若搞不清這兩個方法獲取的究竟是什麼「屬性」,有時就會出現使人困惑的結果。
官方文檔中,用了下面的例子來解釋這二者的不一樣:javascript

<input type="checkbox" checked="checked" />
操做 結果
elem.checked true (Boolean) Will change with checkbox state
$( elem ).prop( "checked" ) true (Boolean) Will change with checkbox state
elem.getAttribute( "checked" ) "checked" (String) Initial state of the checkbox; does not change
$( elem ).attr( "checked" ) (1.6) "checked" (String) Initial state of the checkbox; does not change
$( elem ).attr( "checked" ) (1.6.1+) "checked" (String) Will change with checkbox state
$( elem ).attr( "checked" ) (pre-1.6) true (Boolean) Changed with checkbox state

咱們能夠看到,使用prop()當於直接使用了DOM元素對象的屬性,而attr()至關於使用了DOM元素的getAttribute()setAttribute()方法(而1.6前和1.6後的效果比較特殊,下面會解釋)。這兩種不一樣的實現,決定了兩種方法獲取到的值並不同,這就得涉及到DOM元素屬性(property)和特性(attribute)間的區別了。html

屬性(property)和特性(attribute)

咱們知道DOM的實現就是把一個HTML文檔映射爲一棵DOM樹,而DOM樹上的每一個節點其實就是一個javascript對象。因此DOM元素屬性和普通對象的屬性同樣,就是DOM對象這個javascript對象上的屬性而已,咱們能夠直接在DOM對象上經過.[]來獲取和設置它們,好比:java

<form>
    <input type="text" name="form-item" value="value0">
</form>
var formItem = document.querySelector('[name=from-item]');
console.log(formItem.value); /* value0 */
formItem.value = 'value1'; /* 文本框顯示「value1」,但此時HTML中的value特性仍爲"value0"  */
console.log(formItem.value); /* value1 */

而同時在DOM元素節點以外,還有其餘類型的節點,好比文本節點、註釋節點、還有咱們要討論的特性節點(Attr節點)等等;這些節點固然也是DOM樹上的一個js對象。要操做特性節點,能夠在DOM元素上經過getAttribute()setAttribute()removeAttribute()等方法來實現,或者用attributes屬性獲取特性節點集合再做操做:函數

console.log(formItem.getAttribute('value')); /* value0,不受上面屬性設置的影響,仍保持頁面加載後html中的值 */

formItem.setAttribute('value', 'value2'); /* 文本框仍顯示「value1」,但此時HTML中的value特性已被改成"value2" */
console.log(formItem.getAttribute('value')); /* value2 */
console.log(formItem.value); /* value1,不隨特性節點的改變而改變 */

上面的例子中,尤爲要區分兩點:code

  • 屬性和特性二者不是一一對應的:Attr節點對應的就是HTML各標籤中的特性,這些特性有的未必會被內置爲DOM元素的屬性,好比HTML5的data-*特性等自定義特性;而DOM元素的屬性也未必都是HTML中的特性,好比一些DOM元素的操做方法orm

  • 即便特性節點名和DOM元素的屬性名一致,這二者的操做和行爲也是不一樣的:htm

    • DOM元素的屬性是DOM對象原生實現的,符合通常對象屬性的行爲;這些屬性操做和同名的HTML特性節點無關,但能夠在顯示上覆蓋HTML特性節點的設置對象

    • 對於特性節點的操做都是針對HTML文檔上的特性;對特性的操做不會改變同名屬性值,只是改變HTML的文檔內容而已事件

因此咱們能夠獲得屬性和特性的根本區別了:ip

DOM元素的屬性(property)是該對象所擁有的屬性,而特性(attribute)則是該元素在HTML中的所擁有的特性節點。property是對象屬性,自己不操做特性節點,但能夠覆蓋HTML中的同名特性的效果,是js操做;attribute是DOM節點對象,只用於獲取和設置HTML特性,是文本操做。

用處

經過上面的討論,既然屬性和特性有根本性區別,那也就意味着他們的應用場合不太同樣、也不能混淆:

  • property的操做是純js操做,用於獲取和設置原生的一些特性;而且對於事件屬性如onclick能夠得到處理函數、對於style屬性能夠得到一個對象。

  • attribute的操做是文本操做,用於獲取和設置HTML文檔中的特性內容,注意這些內容都是字符串形式;同時它能操做的特性也不僅是原生限定的那幾種,對於一些拓展特性如data-*也能夠操做。

回到一開始舉的jQuery的例子,elem.checked因爲是屬性操做,因此能夠返回一個布爾值。而elem.getAttribute( "checked" )因爲是針對HTML特性的文本操做,因此返回的就是一個字符串,固然這個字符串的值也未必是"checked",而是由HTML中指定的值決定的。

至於爲何attr方法會在jQuery 1.6以前的版本、1.6自己和1.6以後出現各類不一致的行爲呢?首先prop方法是在1.6版本以後引入的,以前只有attr時,該方法對返回屬性是仍是特性沒有做嚴格區分;而在1.6版本開始會明確讓attr返回特性、prop負責處理屬性,同時1.6後爲考慮向後兼容,attr返回特性會隨屬性的改變而改變,但返回的已經只能是「特性形式」的字符串了。

相關文章
相關標籤/搜索