新聞中心
上周我認(rèn)真分析了一個(gè)Web 頁(yè)面,它在onLoad 事件中處理一段定制腳本文件用了4.8 秒。結(jié)果是其中2.8 秒消耗在動(dòng)態(tài)菜單庫(kù)上(將會(huì)在博客中單獨(dú)記錄),剩下的 2 秒花費(fèi)在jQuery的選擇器上。分析顯示多數(shù)選擇器不返回任何對(duì)象,而那些會(huì)返回對(duì)象的選擇器可考慮用不同的選擇器來(lái)改善性能。

關(guān)于jQuery選擇器
有大量的日志文章論述了jQuery選擇器及它們的性能影響。正如你所知,可以通過(guò) ID, TagName 或 ClassName 選擇元素。依賴于不同的選擇器, jQuery 會(huì)使用瀏覽器本地方法,如 通過(guò) ID 或標(biāo)簽來(lái)選擇元素,或者在使用類名選擇時(shí)須手工從 DOM 中遍歷獲得元素(因?yàn)樵?IE 中不存在相應(yīng)的 getElementsByClssName).
分析我的頁(yè)面時(shí)間中這 2 秒
在 onLoad 處理器中對(duì)頁(yè)面中某些特定的元素使用 jQuery 設(shè)置為隱藏,顯示或改變樣式表...。這里是一個(gè)代碼片斷:
onLoad 中的 jQuery 腳本樣例
在 onLoad 事件處理器中充滿著這樣的調(diào)用。通過(guò)使用免費(fèi)的 dynaTrace AJAX Edition, 你會(huì)看到被解析為選擇器的 $ 調(diào)用,并跟隨著那些方法調(diào)用,選擇器至少都能獲取到一個(gè)對(duì)象。下面通過(guò) PurePath 對(duì) onLoad 事件處理器的觀察,不僅給我們展示了每次選擇器調(diào)用所耗費(fèi)的時(shí)間,還包括在不只一個(gè)對(duì)象時(shí)實(shí)際找到的對(duì)象數(shù)(下面還沒(méi)有哪個(gè)方法調(diào)用是連一個(gè)對(duì)象都找不到的).
非必要的 jQuery 選擇器調(diào)用導(dǎo)致無(wú)謂的開銷
所有紅色標(biāo)記的調(diào)用都未返回一個(gè)元素,因?yàn)椴淮嬖谥苯踊诓樵儣l件的 DOM 元素。JS 列顯示了每一次單獨(dú)方法調(diào)用的執(zhí)行時(shí)間--范圍在 1ms 到大于 100 ms。Size 列告訴了我們每次單獨(dú)的調(diào)用產(chǎn)生了多少次的 JavaScript/DOM 的方法調(diào)用(譯者注:指瀏覽器本地的調(diào)用)。這里我們也能明白,為什么某些 $ 調(diào)用花費(fèi)了那么長(zhǎng)時(shí)間,是因?yàn)樗鼈儗?shí)際進(jìn)行了許多的調(diào)用來(lái)完成請(qǐng)求。Invocation 列告訴了我們?cè)摲椒ū凰母讣?jí)所調(diào)用的頻度。這里我們可看出一些對(duì)象實(shí)際被解析了多次,比如: ".pop-cart"。***的做法應(yīng)該是只解析一次得到對(duì)象并緩存起來(lái)。
這里我們學(xué)到的***課是上面多數(shù)調(diào)用是非必要的,只會(huì)產(chǎn)生過(guò)量的消耗。如果你明確知道你需要解析出哪些頁(yè)面元素,那就不要試圖去解析其他的對(duì)象。我知道,用全局的腳本文件來(lái)處理不同頁(yè)面中的不同內(nèi)容會(huì)導(dǎo)致出現(xiàn)這樣的情況--但是--你是否真愿意在這種無(wú)謂的開銷中生活呢?
分析 jQuery選擇器的差異
在分析頁(yè)面上的***個(gè)問(wèn)題是致使了太多的非必要 $ 調(diào)用。繼而帶來(lái)的另一個(gè)疑問(wèn)就是為何某些 $ 方法響應(yīng)很快(幾微秒),而有些卻用了相當(dāng)長(zhǎng)的時(shí)間(超過(guò) 100ms)。理論上的答案可以參看 jQuery Best Prtice Blog. 回到我的頁(yè)面中來(lái),它向我提示了如下的結(jié)論:
ID 選擇器,也就是使用了 getElementById,是最快的
下圖展示了一個(gè)使用 ID 的選擇器。它使用了 getElementById,因此很快就返回了。
jQuery ID 選擇器
TagName 選擇器使用的是 getElementsByTagName
下面的例子是通過(guò) TagName 搭配 ClassName 來(lái)選擇元素。jQuery 首先使用本地實(shí)現(xiàn) getElementsByTagName 來(lái)獲得所有指定標(biāo)簽的元素。接著遍歷它們針對(duì) ClssName 進(jìn)行過(guò)濾。
jQuery 的 Tag 和 ClassName 選擇器
ClassName 選擇器需要遍歷所有的 DOM 元素
如果你只用 ClassName 選擇器 - jQuery 需要遍歷 DOM 中的每一個(gè)元素,因?yàn)樵?Internet Explorer(對(duì)于 FireFox 是另一番情景) 中沒(méi)有對(duì)應(yīng)于 getElementsByClassName 的本地實(shí)現(xiàn)。下圖顯示了在一直有著 3460 個(gè) DOM 元素的頁(yè)面中選擇器使用開銷的情況。
jQuery ClassName 選擇器
小結(jié)
依賴于你的 Web 站點(diǎn)的大小(指 DOM 元素的數(shù)量 ), 你需要考慮每個(gè)單獨(dú)的選擇器方法的開銷。相比于通過(guò) ClassName 來(lái)選擇,你應(yīng)該優(yōu)先考慮用 TagName 搭配 ClassName 來(lái)選擇,或是在你的頁(yè)面只有少量對(duì)象時(shí)用唯一性的 ID 來(lái)選擇。而且- 確保緩存了已解析獲得的對(duì)象,以避免再次解析調(diào)用時(shí)的開始。還有 - ***也是應(yīng)該予以重視的一點(diǎn) - 避免不必要的調(diào)用。如前面頁(yè)面我所分析的 - 2 秒中有超過(guò) 1.5 秒是可以規(guī)避那些調(diào)用來(lái)省去的。
原文標(biāo)題:101 on jQuery Selector Performance
原文地址:http://blog.dynatrace.com/2009/11/09/101-on-jquery-selector-performance/
分享題目:jQuery選擇器深入分析:避免不必要的調(diào)用
分享網(wǎng)址:http://m.fisionsoft.com.cn/article/djcdijo.html


咨詢
建站咨詢
