1. 程式人生 > >JS效能優化

JS效能優化

   上週接到一個需求,其中涉及到一個好友選擇的元件,就是單機左側某個群組下的好友後該好友移動到右側,視為選擇了它,另外每個群組還有全 選,摺疊和展開等功能。元件在開發過程中,遇到了在2000條資料的時候,搜尋會變的很卡,IE8下為2s左右,IE6更長,我在最初的優化過程中我使用 事件代理,文件片段,字串陣列,少建立物件,快取一切可以快取的,用hash超找代替陣列查詢等方式,但是一直沒有找到效能的瓶頸所在,所以效果不大, 後來採用了setTimeout的方式,就是限制js的執行時間,當它超過規定的時間後記錄當前的執行狀態,然後setTimeout延遲一段時間再執 行,而把延時的這段時間交給UI執行緒,這樣做後確實不卡了,但是因為出現延時呼叫,搜尋的總體時間變長了,試想讓使用者等十多秒來看搜尋的結果這樣做也太不 合理,問題一直沒有得到根本的解決。

   後來,在johnnie和youkun的幫助和提示下,我找到了優化的入口就是找效能瓶頸,就是如果一個段程式碼很耗時的話你可以註釋掉一部分你認為是很耗 時的,或者乾脆全部註釋掉,然後再一點一點的解開,按照這個思路,我發現在我的迴圈搜尋中頻繁進行了dom操作,就比如搜尋使用者提交的一個 queryString,我的方法是在資料中遍歷所有的item,如果匹配,就通過這條資料找到這個item對應的dom,然後顯示它,不匹配就隱藏它, 然後每個組搜尋完還要更新該組搜尋的結果數,這裡面涉及到選擇dom,然後顯示或者隱藏它等,正是這些dom操作在大資料量的時候使得搜尋操作變得很慢, 當時我試驗了下,就算在迴圈中只執行一個document.getElementById也很耗時,找到了問題的根源所在,接下來的優化就有了方向,於是 在v3版本中我改變了搜尋的策略,迴圈遍歷的時候只拼接dom,在迴圈結束後一次性的放到文件中,經過測速,迴圈遍歷拼接dom只用了不超過60ms,而 把這一大段html放到文件中這一個操作在IE下耗時250ms左右,雖然離大師們推薦的100ms還有差距,但是相對v2的2s提升了很多,我也終於鬆 了一口氣了。
 小結:其實js優化一定要掌握方法,沒有正確的方法可能做了很多工作都是偏離主題的,按照正確的優化方法來優化就會定位效能瓶頸,然後對其採取進行有效的 優化措施,而js優化中最主要的還是對dom操作的優化,單純的js執行時間是很短的,而js和dom之間的互動是通過介面來完成,通過介面來完成的都會 有延時,所以要儘量減少dom操作,尤其是在大迴圈中。
 最後,總結下常見的dom操作的優化方法(節選自高效能JavaScript)

 1  最小化dom訪問次數,儘可能在js端執行;
 2  如果需要多次訪問某個dom節點,請使用區域性變數儲存對它的引用;
 3  小心處理html集合,因為它實時連繫著底層的文件,把集合的長度快取到一個變數中,並在迭代中使用它,如果需要經常操作集合,建議把它拷貝到一個數組中;
 4  如果可能的話,使用速度更快的API,比如querySelectorAll和firstElementChild;
 5  要留意重繪和重排;批量修改樣式時,“離線”操作dom樹;使用快取,並減少訪問佈局的次數;
 6  動畫中使用絕對定位,使用拖放代理
 7  使用事件委託來減少事件處理器的數量

 總結下js中對資料訪問的優化(節選自高效能JavaScript)

 1  函式中讀寫區域性變數總是最快的,而全域性變數的讀取則是最慢的;
 2  儘可能地少用with 語句,因為它會增加with 語句以外的資料的訪問代價;
 3  閉包儘管強大,但不可濫用,否則會影響到執行速度以及記憶體;
 4  巢狀的物件成員會明顯影響效能,儘量少用;
 5  避免多次訪問物件成員或函式中的全域性變數,儘量將它們賦值給區域性變數以快取。