jquery選擇器的實現流程簡析及提高效能建議!

weixin_34219944發表於2013-11-28

當我們洋洋得意的使用jquery強大的選擇器功能時有沒有在意過jquery的選擇效能問題呢,其實要想高效的使用jquery選擇器,瞭解其實現流程是很有必要的,那麼這篇文章我就簡單的講講其實現流程,相信會為讀者的jquery優化開發提供一些小的建議。

我們知道jquery的$()函式可以傳很多種引數(document、string、fn、array、number),那麼jquery的init方法就會根據你傳參的型別的不同進入不同的流程。其他的我們今天就不多說了,我們重點講一下對string型別的處理,因為只有它才會觸發jquery的選擇器功能。

1、首先是使用正規表示式檢查是不是建立dom的操作,例如$(“<div></div>”),就是要建立div了;

2、否則就是選擇操作,然後會判斷是不是簡單的id選擇,當然這一步也是正則匹配,jquery在這裡會毫不猶豫的呼叫document.getElementById,無疑,這是最快的選擇了;

3、最後就是直接進入jQuery.fn.find()方法,這裡就是jquery所引用的sizzle選擇器放大光芒的地方了。

從上面我們可以看出來,jquery選擇器只是對簡單的id選擇開了小灶,其他的css選擇很大一部分需要藉助於sizzle,所以說,這裡總結一點,簡單的id選擇是jquery中最快的了。

有的人就說了,我不可能都用id選擇器呀,別急,我們們再看看sizzle強大的選擇功能吧。Sizzle是jquery從1.3版本開始引入的選擇引擎。我們一般實現的選擇的選擇器模式(也包括jquery 1.2)都是Left To Right模式,而sizzle卻別出新格,使用了Right To Left(以下我們簡稱RTL),說的是不是有點迷了,別急我們們結合例子給大家說明一下:

例 1:$(“div a”)

一般的選擇流程(LTR):

1、選擇頁面中所有的div

2、選擇div下的所有a標籤

3、合併結果集,返回結果集

Sizzle的選擇流程(RTL):

1、選擇頁面中所有的a標籤

2、判斷a標籤的父節點是否為div標籤,是則push,否則shift

3、返回結果集

有沒有發現,RTL的選擇模式其實是少了一個合併操作,不要小看這一步,其實節省了很多時間,這就是sizzle能夠高效的選擇結果集的訣竅之一,其實從sizzle的這一點就給了我們一個高效選擇的建議,多使用Right To Left的選擇模式。

下面我們們看一下這麼一個選擇:$('#test span'),相信很多人都是用過類似這種的選擇模式,那麼其實現流程呢?Jquery是通過$().find()方法啟用sizzle的,上面寫的這種模式會有一個函式判斷啟用find,然後才呼叫sizzle,那麼我們們再看一看另外一種相同的選擇:$(“#test”).find(“span”),這種方法則會跳過find函式判斷,直接啟用sizzle,這一點改變,執行效率能夠提升8倍多,而且選擇結果相同,大家可以使用firebug測試一下喲(使用console.profile("效能1")),這就給了我們另一個建議,多使用find方法代替css層級選擇。

我們們再看一個選擇方法:$('span:eq(0)'),通過firebug可以看到,這個選擇方法呼叫了34次函式,而結果相同的 $('span').first()卻只呼叫了14次,執行時間前者是後者的將近20倍,過濾函式的優化效應可見一斑呀。Sizzle在這裡有一個判斷,如果存在位置資訊(例如 eq,first等)就會執行LTR選擇模式,遞迴呼叫sizzle,大大降低執行效率,所以這裡我建議,多使用過濾選擇器,可以有效提高執行速度。

這裡就簡單的介紹到這裡,其實我感覺只要能夠做到上面的幾點就能很好地提高jquery的選擇速度了。

個人整理,歡迎評錯。

 

相關文章