讀高效能Javascript筆記
把一段內嵌指令碼放在引用外鏈樣式表的 標籤之後,會導致頁面阻塞去等待樣式表的下載.
這樣做是為了內嵌指令碼在執行時能夠獲得最精準的樣式資訊.下載同一個 CDN 下的多個 JS 檔案,可以這麼寫:
<script src="http://apps.bdimg.com?/libs/jquery/2.1.4/jquery.min.js&libs/angular.js/1.5.0-beta.0/angular-animate.min.js"></script>
等同於
<script src="http://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js" ></script>
<script src="http:http://apps.bdimg.com/libs/angular.js/1.5.0-beta.0/angular-animate.min.js"></script>
這樣就可以使用一個 script 標籤下載多個 javascript 檔案.減少了 HTTP 請求
defer, async 新增到標籤中,下載時並行下載不進行阻塞.區別是 async 下載完成後立即執行與順序無關. defer 按標籤順序執行,且執行在 window.onload 之前
Javascript 載入優化方案:
- 閉合之前,將所有
try {
// code may throw error
} catch (e) {
handleError(e)
}
這樣由於只執行了一條語句且沒有區域性變數的訪問,作用域的臨時改變不影響效能.
使用閉包的時候應該注意: 在頻繁的訪問跨作用域的識別符號時,每次訪問都會帶來效能損失,解決方案是將常用的外部變數儲存在區域性變數中,然後訪問區域性變數.
因為在各個瀏覽器中的 JS 引擎 與 DOM 渲染引擎都是兩個相互獨立的部分,僅通過對外暴露的介面呼叫,因為呼叫需要額外的開銷,所以要儘量減少 DOM 操作.
如果在對效能有苛刻要求的地方更新一大段 html ,推薦使用 innerHTML ,因為它在大部分的瀏覽器中都支行的更快,但在日常操作中它與原生方法沒有任何區別.
HTML 集合是包含 DOM 節點引用的類陣列物件:
- document.getElementsByName()
- document.getElementsByClassName()
- document.getElementsByTagName()
- document.forms
- document.images
- document.links
- document.forms[0].elements
HTML 集合一直與文件保持著連線,具有實時性,所以很影響效率.建議拷貝到普通陣列中,然後進行操作.
在現代瀏覽器中可以使用瀏覽器商提供的 API 來替代 DOM 屬性以獲取更高的效率.
瀏覽器商提供屬性 | DOM 屬性 |
---|---|
children | childNodes |
childrenElementCount | childNodes.length |
firstElementChild | firstChild |
lastElementChild | lastChild |
nextElementSibling | nextSibling |
previousElementSibling | previousSibling |
12. 獲取以下屬性或呼叫方法,會強制重新整理重排佇列並立即執行
- offsetTop offsetLeft offsetWidth offsetHeight
- scrollTop scrollLeft scrollWidth scrollHeight
- clientTop clientLeft clientWidth clientHeight
- getComputedStyle()
因為重繪和重排代價非常高,所以要減少修改次數.比較高效的操作是合併所有改變然後一次處理,如使用 cssText 屬性
el.style.cssText = 'width:200px;height:200px;'
要批量修改的時候,為了避免多次的重繪與重排,我們可以這麼操作
- 使元素脫離文件流
- 編輯修改
- 將元素放回文件流
這樣做,有三種方案:
1. 隱藏元素,應用修改,重新顯示
display:'none' => // happychange// => display:'block'
2. 使用文件片段, fragment 在當前文件外構建,再拷貝迴文檔
3. 將元始元素拷貝到一個脫離文件的節點中,修改副本,完成之後再替換原始元素.動畫操作時涉及到了大量樣式操作,會涉及很多重繪與重排,極大的浪費了計算資源,可以用以下步驟避免
- 使用絕對定位,使元素脫離文件流
- 動畫重繪,變更.因為這已經脫離了文件流了,只是小面積的重繪,不影響大部.
- 動畫結束之後恢復定位.
使用事件委託來減少事件處理器的數量.
迴圈速度的優化:
減少屬性查詢:
for(let i=0,j=arr.length;i<j;i++){ // code }
倒序操作:
for(let i = arr.length;i--;){ // code }
書上提到了達夫裝置,我試驗了一下,沒啥卵用.可以是我不會使用吧,總之別在那上面浪費時間了.