我熱愛 jQuery,且儘管我認為自己算是一名高階 JavaScript 開發者,我從來沒有試過由頭到尾把 jQuery 的原始碼看一遍,直到現在。這裡分享一些我一路下來學到的東西:
注意:我使用 $.fn.method()
語法來表示呼叫一組匹配元素的方法。比如當我說 $.fn.addClass
,則表示$('div').addClass('blue')
或者 $('a.active').addClass('in-use')
此類的用法。$.fn
是 jQuery 包裝元素的原型。
1. Sizzle 的權重:Sizzle 是 jQuery 用於在 DOM 找元素的的選擇器引擎,基於 CSS 選擇器。正是它將 $('div.active')
轉換成可操作的元素陣列。我知道 Sizzle 佔了 jQuery 相當大的部分,但它的龐大還是嚇到了我。按行數來說它很無疑是 jQuery 中唯一最龐大的特性。我估計它佔了總程式碼庫的 22%,而第二大的特性—— $.ajax
只佔了 8%。
2. $.grep:這個方法與 Underscore 的 _.filter
類似。接受兩個引數,一個元素陣列和一個函式,對每個元素依次執行函式,返回執行結果為 true 的元素陣列。
3. 冒泡禁止:jQuery 明文禁止 load
事件冒泡。從內部看,jQuery 在所有的 load
事件中傳入特殊的 noBubble: true
標記,所以 image.load
事件才不會冒泡到 window
上錯誤地觸發 window.load
事件。
4. 預設動畫速度:jQuery 通過快速連續地改變樣式屬性來實現元素動畫效果。每一次小改變被稱作一個 tick
。預設動畫速度是每13毫秒執行一次 tick
,要改變速度你可以重寫 jQuery.fx.interval
成你想要的整數。
5. fn.addClass 可以接受函式:我們通常向 $.fn.addClass
提供一個包含類名的字串來建立元素。但它也可以接受一個函式。這個函式必須返回一個字串,多個類名間要以空格隔開。這裡還有個彩蛋,這個函式接受已匹配元素的索引作為引數,你可以用這個特性來構造智慧變化的類名。
6. fn.removeClass 也一樣:與上文的一樣,它也可以接受一個函式。這個函式也會自動接收元素的索引。
7. :empty 偽選擇器:可以方便地用來匹配沒有孩子的元素。
8. :lt 與 :gt 偽選擇器:它們會根據元素在匹配集合中的索引來匹配元素。比如 $('div:gt(2)')
會返回所有的 div
,除了前三個(從0開始)。如果你傳入一個負數,它會倒過來從尾開始數。
9. $(document).ready() 的承諾: jQuery 貌似是用回了自己的東西。在內部,可信賴的 $(document).ready()
使用了一個 jQuery 延遲來確定 DOM 在什麼時候完全載入。
10. $.type: 大家肯定能熟練使用 typeof
來確定資料型別,但你知不知道 jQuery 提供了一個 .type()
方法?jQuery 版比原生版更加智慧。比如 typeof (new Number(3))
返回 object
,而 $.type(new Number(3))
則返回 number
。更新:正如 ShirtlessKirk 在評論中指出,$.type
返回其物件的 .valueOf()
屬性。所以更準確的說法應該是 $.type
告訴你一個物件的返回值的型別。
11. $.fn.queue:你可以通過 $(‘div’).queue()
檢視一個元素的效果佇列,很方便地瞭解元素還剩餘多少效果。更有用的是,你可以直接操作佇列去新增效果。從 jQuery 文件摘錄的:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
$( document.body ).click(function() { $( "div" ) .show( "slow" ) .animate({ left: "+=200" }, 2000 ) .queue(function() { $( this ).addClass( "newcolor" ).dequeue(); }) .animate({ left: "-=200" }, 500 ) .queue(function() { $( this ).removeClass( "newcolor" ).dequeue(); }) .slideUp(); }); |
12. 禁用元素不會觸發 click 事件:jQuery 預設不會為禁用的元素執行 click
事件,有了這個優化,你無需自己用程式碼再檢查一遍。
13. $.fn.on 可以接受物件:你知道 $.fn.on
可以接受一個物件來一次過連線多個事件嗎?jQuery 文件的例子:
1 2 3 4 5 6 7 8 9 |
$( "div.test" ).on({ click: function() { $( this ).toggleClass( "active" ); }, mouseenter: function() { $( this ).addClass( "inside" ); }, mouseleave: function() { $( this ).removeClass( "inside" ); } }); |
14. $.camelCase:這個有用的方法可以將連字元式的字串轉換成駝峰式的字串。
15. $.active:呼叫 $.active
返回 XHR (XML Http Request) 查詢的個數。利用它可以手動制定 AJAX 請求的併發上限。
16. $.fn.parentsUntil / $.fn.nextUntil / $.fn.prevUntil:我比較熟悉 .parents()
、.next()
和 .prev()
,卻不知道原來還有其它的方法。它們會匹配所有的 雙親/下一個/前一個 元素直到(until)遇到符合終止條件的元素。
17. $.fn.clone 引數:當你用 .clone()
克隆一個元素,你可以用 true
作為第一個引數來克隆該元素的資料屬性(data attributes)和事件。
18. 更多的 $.fn.clone 引數:除了上面的方法外,你還可以再傳多一個 true
引數來克隆該元素所有孩子的資料屬性和事件。這叫做“深克隆”。第二個引數的預設值與第一個一樣(第一個預設false)。所以當第一個引數是 true
而你想讓第二個引數也是 true
時,完全可以忽略第二個引數。