本文較為詳細的分析了jQuery源碼解讀之addClass()方法。分享給大家供大家參考。具體分析如下:
給jQuery原型對象擴展addClass功能,jQuery.fn就是jQuery.prototype
代碼如下:jQuery.fn.extend({
/*
可以看出這是一個函數名叫addClass的插件方法。
*/
addClass: function( value ) {
var classes, elem, cur, clazz, j, finalValue,
i = 0,
/*
this表示選擇器選擇的准備添加class的jQuery對象,len是該jQuery對象數組的長度。
*/
len = this.length,
//在有一個操作數不是布爾值的情況下,&&操作就不一定返回布爾值,此時,它遵循下列規則:
//1.如果第一個操作數不是布爾類型,則返回第二個操作數;
//2.如果第二個操作數不是布爾類型,則只有在第一個操作數的求值結果為true,的情況下才會返回該對象;
//3.如果兩個操作數都不是布爾類型,則返回第二個操作數;
//4.如果有一個操作數是null,則返回null;
//5.如果有一個操作數是NaN,則返回NaN;
//6.如果有一個操作數是undefined,則返回undefined 。
//情況1:如果value是null,符合規則4,返回null,即proceed值為null;
//情況2:如果value是undefine,符合規則6,返回undefined,即proceed值為undefined;
//情況3:如果value是NaN,符合規則5,返回NaN,即proceed值為NaN;
//情況4:如果value是數字類型,返回false;
//情況5:如果value是布爾類型,返回false;
//情況7:如果value是Array,Object,Function類型,符合規則2,但typeof value === 'string'是false,所以返回該對象,返回false。
//情況8:如果value是字符串類型,符合規則2,返回value。
//因此,這句只能判斷value是不是字符串類型,並且返回這個字符串賦值給proceed。其他任何類型最後都返回false,或是可被隱式轉換為false的類型。
proceed = typeof value === "string" && value;
//由於上面只能判斷是否是字符串類型,下面這句是判斷value是否為Function類型。使用了jQuery的全局函數isFunction判斷,就是$.isFunction()。
if ( jQuery.isFunction( value ) ) {
//如果value是Function類型,進到這裡了。
//返回jQuery對象,為了鏈式調用。
//這裡的this是你選擇器選擇的jQuery對象。
return this.each(function( j ) {
//開始迭代,這裡的this可不是jQuery對象了,是當前迭代的DOM對象,所以用jQuery(this)包裝了一下,成為一個jQuery對象,這樣就可以使用jQuery方法。j表示每次遍歷的索引。傳遞一個用來設置類名的有返回值的value函數。value這個函數每次call當前DOM為其執行對象,並傳入當前DOM索引值和類名,value函數返回的值,由jQuery(this).addClass(返回值)再次調用addClass()方法。如果返回的是字符串,就執行另外一個if的分支。如果返回的還是function,則繼續調用返回的這個function。
jQuery( this ).addClass( value.call( this, j, this.className ) );
});
}
//之前得到proceed是字符串,這裡判斷下是否為空字符串,非空字符串隱式轉換為true。空字符串隱式轉換為false哦,那麼if語句塊就不再執行了,程序跳到最後的return this,返回這個jQuery對象就執行完了。
if ( proceed ) {
//proceed非空字符串,開始執行if語句塊。假定value是"show bd1"。
//rnotwhite是正則表達式(/\S+/g),意思是全局匹配非空白字符一次或更多次。
//(value || "")返回"show bd1",很簡單。
//"show bd1".match((/\S+/g)) || []返回["show", "bd1"],match不知道什麼作用的同學快去查查吧。
classes = ( value || "" ).match( rnotwhite ) || [];
//現在classes是['show', 'bd1']一個你要添加類名的數組。
//下面開始遍歷,為每一個DOM對象添加類。
for ( ; i < len; i++ ) {
//this是jQuery對象,elem是當前DOM對象。
elem = this[ i ];
/*
===操作符比&&操作符優先級高,先判斷DOM節點類型是否是元素節點。
rclass是正則表達式/[\t\r\n\f]/g;
括號內的三目運算符表示,當前DOM節點是否已經有class,有的話,則將class中可能存在的制表符,換行符,回車符等替換為帶有一個空格的字符串" ",並且給當前class的前後各加一個空格;如果當前DOM節點還沒有class,則也是給一個帶一個空格的字符串" "。最後變成
cur = elem.nodeType === 1 && "show bd1",這個很熟悉啊,沒錯,根據最開始的那6個規則求值。
假定elem的節點類型是1,那麼 cur = true && " ",最後cur = "show bd1"。
如果elem的節點類型不是1,那麼 cur = false && " ",最後cur = false。
*/
cur = elem.nodeType === 1 && ( elem.className ?
( " " + elem.className + " " ).replace( rclass, " " ):" ");
//現在cur = " show bd1 ",進入if語句塊執行。
if ( cur ) {
j = 0;
/*
classes為["show bd1"]
循環檢查要添加的類是否已經存在與當前DOM元素已經有的類裡。
如果沒有,則添加這個類。
*/
while ( (clazz = classes[j++]) ) {
if ( cur.indexOf( " " + clazz + " " ) < 0 ) {
cur += clazz + " ";
}
}
/*
最後用$.trim()將類" show bd1 "兩頭的空格字符去掉。
檢查當前DOM元素的類是否和拼接好的類重復。避免不必要的重復添加相同類的渲染。
*/
finalValue = jQuery.trim( cur );
if ( elem.className !== finalValue ) {
elem.className = finalValue;
}
}
}
}
//返回這個jQuery對象,為了以後的鏈式調用。
return this;
}
});
希望本文所述對大家的jQuery程序設計有所幫助。