瞭解JS效能最佳化是學習前端必備的一項技能。下面我們來總結js效能最佳化方法:
1.注意範圍,避免全域尋找。
訪問全域變數比訪問局部變數慢,是因為需要遍曆範圍鏈,尋找範圍鏈需要額外的時間。所以在一個函數中,將訪問多次的全域對象或者域外變數儲存為局部變數來使用。如某個方法需引用全域變數的值,則在該方法所在的對象的範圍中定義一個局部變數等於全域變數的值。
避免不必要的屬性尋找,將屬性設定為局部變數。
function(){
var title = document.title;
for(var i=0;i<3;i++){
console.log(title);
}
}
2.最佳化迴圈
簡化迴圈體。當迴圈的數量不多時,展開迴圈。當if-else較多時,建議使用switch語句。
3.最小化語句數
聲明多個變數時,可以使用一個var關鍵字來聲明,變數之間用逗號表示。
使用數組或對象字面量來建立數組或對象。var arr= [1,2,3,4];var map={a:1,b:2}
4.JS的執行盡量脫離DOM樹,限制DOM操作的次數,最佳化DOM互動,盡量減少瀏覽器對DOM的渲染和重繪操作
最小化現場更新,現場更新就是立即對頁面的顯示進行更新。盡量少更新。這時候可使用文檔片段來構建DOM結構。document.createDocumentFragment()
使用innerHTML來構建大的DOM結構。但是也避免重複大量的使用。
5.使用事件代理
頁面上的事件處理常式的數量和頁面響應使用者互動的速度之間有個負相關。所以為了減少事件處理常式,盡量使用事件委託技術。
6.JS的執行順序
JS放HTML頁面最後面時,不一定提升JS效能,但是在網速較慢的時候會快速的渲染頁面。
7.JS定義行為,html定義內容,CSS定義外觀,不混淆
8.減少HTTP請求數,JS壓縮,HTTP壓縮
9.資料盡量儲存在數組裡
10、代碼的最佳化不是減少代碼量,而是增加代碼提高代碼的可閱讀性。
包括正確標記變數,封裝某個重複的行為,合理的注釋等。
11.避免過多的重排與重繪操作。
盡量將DOM中的多個讀操作放一起,中間不要插入寫的操作,因為寫操作會導致瀏覽器迅速的重排,從而影響效能。將DOM中的多個寫操作放一起,不要插入讀的操作,如果插入讀操作會導致瀏覽器多次重排。也就是DOM中讀寫操作分開。
12.緩衝重排擷取的值
避免下次用到該值的時候,瀏覽器又需要重排。
13.通過設定樣式名來修改元素樣式
通過改變元素的class,或者csstext屬性來改變元素的樣式。
14.盡量使用離線DOM來動作節點
例如操作Document Fragment對象,完成後把這個對象插入到實際的DOM中。或者cloneNode()方法,在複製的節點上操作,再用複製的節點替換原節點。
15.對操作頻繁的元素使用display:none,然後對其操作,操作完後恢複顯示display:block
這樣處理的話,瀏覽器相當於渲染頁面只有兩次(隱藏或顯示)。不可見的元素不影響重排或重繪。
16.將元素設為position:fixed或absolute,重排的開銷會很小
因為被定位的元素不會影響其他元素的布局。
17.使用虛擬DOM的指令碼庫
比如React等。
18.使用window.requestAnimationFrame(),window.requestIdleCallback()
這兩個方法調節重新渲染。
requestAnimationFrame(func),傳一個函數進去當作參數,這個函數是一個螢幕重繪前被調用的函數,等下次瀏覽器渲染時執行函數裡的操作。其實這個跟setTimeout()類似,只是間隔時間是由瀏覽器自己(下次渲染)來決定。這個方法解決了瀏覽器不知道Javascript動畫正在執行和不知道多少才是合適的間隔的問題。
相容寫法:mozRequestAnimationFrame() || msRequestAnimationFrame() || weibkitRequestAnimationFrame() || oRequestAnimationFrame()
使用情境比如:重複執行的函數,JS動畫(滑動),頁面滾動,頁面放大縮小等。
案例:
<script>
function scroll(elem){
var hei = elem.clientHeight;
window.requestAnimationFrame(function(){
elem.style.height = (hei*2) + 'px';
})
}
function scroll2(elem){
var hei = elem.clientHeight;
elem.style.height = (hei*2) + 'px';
}
elem = document.getElementById('elem');
console.time('a');
for(var i=0;i<100000;i++){
scroll(elem);
}
console.timeEnd('a');
console.time('b');
for(var i=0;i<100000;i++){
scroll2(elem);
}
console.timeEnd('b');
</script>
log裡輸出:
a: 389.112ms
b: 3922.486ms
很明顯,使用requestAnimationFrame()方法後執行更有效率。不過該方法也有相容性問題,是否使用還得看項目而定。