jQuery的attr與prop

謙行發表於2013-10-01

jQuery1.6中新新增了一個prop方法,看起來和用起來都和attr方法一樣,這兩個方法有什麼區別呢?這要從HTMl 的attribute與property區別說起,attr與prop正是這兩個東西的縮寫。

attribute與property

attribute和property都可以翻譯為屬性,為了以示區別,通常把這兩個單詞翻譯為屬性與特性。

<div id="test">Click Here</div>

上面這段HTML語句中有三個節點,分別是Element “div”、attribute “id”、Text “click here”,我們最常見的attribute正式指的attribute型別節點,在JavaScript有專門處理attribute的函式 .getAttribute(name) / setAttribute(name,value)。當然attribute不只是我們能夠在HTML文件上看到的這幾個,我們可以自定義attributed加到DOM節點中

<div id="test">123</div>
    
    <script type="text/javascript">
        var t=document.getElementById('test');
        t.setAttribute('class','active');
        t.setAttribute('customizedAttr','customized');
    </script>

這樣可以div被修改為

<div id="test" class="active" customizedattr="customized">123</div>

通過方法 setAttribute設定的attribute最終都會反映到元素的attribute型別的節點中

property是DOM物件的欄位,跟我們平常使用的一些物件一樣,包含很多欄位,這些欄位就是property,取值或者設定值和普通欄位一樣通過”物件.欄位“的方式。

看起來attribute和property應該沒有什麼關係才對,怎麼會。。。attribute和property容易混倄是因為很多attribute節點還有一個相對應的property屬性,比如上面div的”id“ attribute 同樣可以用t.id取到(實際上絕大部分人都是這樣獲取的),通過property更改id後,用getAttibute獲取的id是更新後的id。

t.id='test1';
console.log(t.getAttribute('id'));//test1

同樣我們也可以自定義property

t.customizedProp='customized prop';

區別

1. 於build-in屬性,attribute和property共享資料,attribute更改了會對property造成影響,反之亦然,但是兩者的自定義屬性是獨立的資料,即使name一樣,也互不影響,看起來是下面這張圖,但是IE6、7沒有作區分,依然共享自定義屬性資料

2. 並不是所有的attribute與對應的property名字都一致,比如剛才使用的attribute 的class屬性,使用property操作的時候應該是這樣className

t.className='active2';

3. 對於值是true/false的property,類似於input的checked attribute等,attribute取得值是HTML文件字面量值,property是取得計算結果,property改變並不影響attribute字面量,但attribute改變會一向property計算

<input id="test3" type="checkbox"/>
var t=document.getElementById('test3');
        console.log(t.getAttribute('checked'));//null
        console.log(t.checked);//false;
        
        t.setAttribute('checked','checked');
        console.log(t.getAttribute('checked'));//checked
        console.log(t.checked);//true
        
        t.checked=false;
        console.log(t.getAttribute('checked'));//checked
        console.log(t.checked);//false

 

4. 對於一些和路徑相關的屬性,兩者取得值也不盡相同,但是同樣attribute取得是字面量,property取得是計算後的完整路徑

<a id="test4" href="#">Click</a>
var t=document.getElementById('test4');
        console.log(t.getAttribute('href'));//#
        console.log(t.href);//file:///C:/Users/bsun/Desktop/ss/anonymous.html#

關於瀏覽器(IE)造成的相容性問題可以看看IE 混淆了 DOM 物件屬性(property)及 HTML 標籤屬性(attribute),造成了對 setAttribute、getAttribute 的不正確實現

attr和prop

相信看完上面內容,大家就明白為什麼jQuery要新增prop方法了,在jQuery API中也有專門解釋

Attributes VS. Properties

在一些特殊的情況下,attributes和properties的區別非常大。在jQuery1.6之前,.attr()方法在獲取一些attributes的時候使用了property值,這樣會導致一些不一致的行為。在jQuery1.6中,.prop()方法提供了一中明確的獲取property值得方式,這樣.attr()方法僅返回attributes。

比如,selectedIndex, tagName, nodeName, nodeType, ownerDocument, defaultChecked, 和defaultSelected應該使用.prop()方法獲取/設定值。 在jQuery1.6之前這些不屬於attribute的property需要用.attr()方法獲取。這幾個並沒有相應的attibute,只有property。

關於布林型別 attributes,比如一個這樣的HTML標籤,它在JavaScript中變數名為elem

<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

根據W3C forms specification,checked屬性是一個布林值,這就意味著只要checked屬性在HTML中表現出來了,那麼相應的property就應該是true,即使checked沒有值,這點兒對其它布林型別的屬性一樣適用。

然而關於checked 屬性需要記住的最重要的一點是:它和checked property並不是一致的。實際上這個attribute和defaultChecked property一致,而且只應該用來設定checkbox的初始值。checked attribute並不隨著checkedbox的狀態而改變,但是checked property卻跟著變。因此瀏覽器相容的判斷checkebox是否被選中應該使用property

if ( elem.checked )
if ( $( elem ).prop( "checked" ) )
if ( $( elem ).is( ":checked" ) )

這對其它一些類似於selected、value這樣的動態attribute也適用。

在IE9之前版本中,如果property沒有在DOM元素被移除之前刪除,使用.prop()方法設定DOM元素property(簡單型別除外:number、string、boolean)的值會導致記憶體洩露。為了安全的設定DOM物件的值,避免記憶體洩露,可以使用.data()方法。

使用場景

其實明白了上面講的內容,什麼時候該使用.attr()什麼時候該使用 .prop()就很清楚了,不過還是傳一張坊間很流行的圖

image

相關文章