JavaScript 性能優化

更多文章

加載與執行

  • <script>標籤放在</body>前面,不要放在<head>中,防止形成堵塞
  • 儘可能減小請求,單個100KB的文件比4個25KB的文件更快,也就是說減小頁面中外鏈的文件會改善性能
  • 儘可能使用壓縮過的JS文件,體積更小,加載更快

數據存取

  • 使用局部變量和字面量比使用數組和對象有更少的讀寫消耗
  • 儘量使用局部變量代替全局變量
  • 如無必要,不要使用閉包;閉包引用着其餘做用域的變量,會形成更大的內存開銷
  • 原型鏈不要過深、對象嵌套不要太多
  • 對於屢次訪問的嵌套對象,應該用變量緩存起來

DOM編程

  • 不要頻繁修改DOM,由於修改DOM樣式會致使重繪(repaint)和重排(reflow)
  • 若是要修改DOM的多個樣式能夠用cssText一次性將要改的樣式寫入,或將樣式寫到class裏,再修改DOM的class名稱
const el = document.querySelector('.myDiv')
el.style.borderLeft = '1px'
el.style.borderRight = '2px'
el.style.padding = '5px'

可使用以下語句代替css

const el = document.querySelector('.myDiv')
el.style.cssText = 'border-left: 1px; border-right: 2px; padding: 5px;'

cssText會覆蓋已存在的樣式,若是不想覆蓋已有樣式,能夠這樣node

el.style.cssText += ';border-left: 1px; border-right: 2px; padding: 5px;'
  • 避免大量使用:hover
  • 使用事件委託
<ul>
  <li>蘋果</li>
  <li>香蕉</li>
  <li>鳳梨</li>
</ul>

// good
document.querySelector('ul').onclick = (event) => {
  let target = event.target
  if (target.nodeName === 'LI') {
    console.log(target.innerHTML)
  }
}

// bad
document.querySelectorAll('li').forEach((e) => {
  e.onclick = function() {
    console.log(this.innerHTML)
  }
}) 

批量修改DOM

當你須要批量修改DOM時,能夠經過如下步驟減小重繪和重排次數:git

  1. 使元素脫離文檔流
  2. 對其應用多重改變
  3. 把元素帶回文檔中

該過程會觸發兩次重排——第一步和第三步。若是你忽略這兩個步驟,那麼在第二步所產生的任何修改都會觸發一次重排。

有三種方法可使DOM脫離文檔:github

  • 隱藏元素,應用修改,從新顯示
  • 使用文檔片段(document.fragment)在當前DOM以外構建一個子樹,再把它拷迴文檔
  • 將原始元素拷貝到一個脫離文檔的節點中,修改副本,完成後再替換原始元素

算法和流程控制

  • 改善性能最佳的方式是減小每次迭代的運算量和減小循環迭代次數
  • JavaScript四種循環中for while do-while for-in,只有for-in循環比其餘其中明顯要慢,由於for-in循環要搜索原型屬性
  • 限制循環中耗時操做的數量
  • 基於函數的迭代forEach比通常的循環要慢,若是對運行速度要求很嚴格,不要使用
  • if-else switch,條件數量越大,越傾向於使用switch
  • 在判斷條件多時,可使用查找表來代替if-else switch,速度更快
switch(value) {
  case 0:
    return result0
    break
  case 1:
    return result1
    break
  case 2:
    return result2
    break
  case 3:
    return result3
    break

}

// 可使用查找表代替
const results = [result0, result1, result2, result3]
  • 若是遇到棧溢出錯誤,可使用迭代來代替遞歸

字符串

str += 'one' + 'two'

此代碼運行時,會經歷四個步驟:算法

  1. 在內存中建立一個臨時字符串
  2. 鏈接後的字符串 onetwo 被賦值給該臨時字符串
  3. 臨時字符串與str當前的值鏈接
  4. 結果賦值給str
str += 'one' 
str += 'two'

第二種方式比第一種方式要更快,由於它避免了臨時字符串的產生編程

你也能夠用一個語句就能達到一樣的性能提高數組

str = str + 'one' + 'two'

快速響應用戶界面

  • 對於執行時間過長的大段代碼,可使用setTimeoutsetInterval來對代碼進行分割,避免對頁面形成堵塞
  • 對於數據處理工做能夠交由Web Workers來處理,由於Web Workers不佔用瀏覽器UI線程的時間

編程實踐

  • 使用Object/Array字面量
const obj = new Object()
const newObj = {}

const arry = new Array()
const newArry = []

使用字面量會運行得更快,而且節省代碼量瀏覽器

  • 位操做在JavaScript中性能很是快,可使用位運算來代替純數學操做
x =* x
// 用位運算代替 
x <<= 1
  • 如無必要,不要重寫原生方法,由於原生方法底層是用C/C++實現的,速度更快

參考資料

高性能JavaScript緩存

相關文章
相關標籤/搜索