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
咱們知道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
返回特性會隨屬性的改變而改變,但返回的已經只能是「特性形式」的字符串了。