前端小白的成長之路 前端系列—代碼性能調優

測試工具

工欲善其事,必先利其器。關於js代碼片斷的測試,長期以來你們都是經過console.timeEnd相似的方式記錄時間來完成的。html

這裏也糾正上述方式可靠性,咱們初中學習對照實驗時,知道經過控制變量法才能驗證某一變量對實驗結果的影響。測試代碼也應該如此。js所運行的設備和環境,對測試的結果不可謂不大。html5

道理先講到這,下面安利工具---jsperf,除了UI有點醜,好像沒啥槽點!ios

調優方向

1.循環優化

image

2.合併DOM操做

image

除了上例外,引發頁面重排和迴流的操做,也應該儘可能合併操做。web

觸發重排操做axios

1. 頁面初始渲染
2. 添加/刪除可見DOM元素
3. 改變元素位置 ----- 定位屬性及浮動 osition,float
4. 改變元素尺寸(寬、高、內外邊距、邊框等----- 盒子模型相關屬性height,padding ,margin , display ,border-width ,min-height
5. 改變元素內容(文本或圖片等)text-align,line-height,vertival-align,overflow , font-size,font-family,font-weight
6. 改變窗口尺寸
7. 獲取元素的offsetWidth、offsetHeight、clientWidth、clientHeight、width、height、scrollTop、scrollHeight,請求了getComputedStyle(), 或者 IE的 currentStyle
複製代碼

觸發迴流操做數組

頁面中的元素更新外觀或風格相關的屬性時就會觸發重繪,如:background,color,visibility, border-style ,border-radius outline-color,cursor,text-decoration, box-shadowpromise

3. 異步併發優化promise.all

await axios.get('https://www.baidu.com/')
  await axios.get('https://juejin.im')
複製代碼

運行時長由兩個異步時間相加決定瀏覽器

const P1 = axios.get('https://www.baidu.com/')
  const P2 = axios.get('https://juejin.im')
  await Promise.all([P1, P2])
複製代碼

運行時長由兩個異步中較長的時間決定bash

4. 尾遞歸優化

這裏引用阮一峯老師的三句話來描述尾遞歸併發

咱們知道,函數調用會在內存造成一個"調用記錄",又稱"調用幀"(call frame),保存調用位置和內部變量等信息。若是在函數A的內部調用函數B,那麼在A的調用記錄上方,還會造成一個B的調用記錄。等到B運行結束,將結果返回到A,B的調用記錄纔會消失。若是函數B內部還調用函數C,那就還有一個C的調用記錄棧,以此類推。全部的調用記錄,就造成一個"調用棧"。

尾調用因爲是函數的最後一步操做,因此不須要保留外層函數的調用記錄,由於調用位置、內部變量等信息都不會再用到了,只要直接用內層函數的調用記錄,取代外層函數的調用記錄就能夠了。

函數調用自身,稱爲遞歸。若是尾調用自身,就稱爲尾遞歸。

注意:函數最後return的只能是一個單純的函數調用,函數調用不能再與其餘表達式作計算

const cumulative = (n) => {
  if (n === 1) return 1;
  return cumulative(n - 1) + n;
}
複製代碼

優化後:

const cumulative = (n, total) => {
  if (n === 1) return total + 1;
  return cumulative(n - 1, n + total);
}
複製代碼

5. 對性能消耗大的操做,適當使用防抖節流

例如在監聽resize、scroll、mousemove等操做時

window.addEventListener('scroll',() => {
    let timer ;
    let startTime = new Date();
    return () => {
        let curTime = new Date();
        if(curTime - startTime >= 2000){
            timer = setTimeout(() =>{
                ...
            },500);
            startTime = curTime;
        }

    }
}());
複製代碼

你還能作的嘗試

突破單線程:webworker

處理密集運算:simd

突破js:WebAssembly

不建議優化的方向

1.原生方法的微觀比較

const arr = [];
arr[arr.length] = 1;
arr.push(1);
複製代碼

已經忘記是哪位大佬告訴我,數組往末端添加一個元素,前者比後者快。 對於js如今這樣的快速發展,就算當下環境是如此,可是隻不定哪一個標準就會對其中的方法最優化,探究這樣細節的比較,大多數狀況下是沒有意義的

2.針對單一瀏覽器或設備的重度優化

觀點同上,對單個設備或瀏覽器的比較優化,卻不知其迭代速度遠快於js標準,在這上面花時間一樣沒有必要

參考

《你所不知道的js》 中卷

相關文章
相關標籤/搜索