我們前面講述都是編寫(xiě)的代碼導(dǎo)致內(nèi)存泄露如何去排查讼呢,但是如何去寫(xiě)出高性能的JS代碼
如何精準(zhǔn)測(cè)試JavaScript性能
- 本質(zhì)上就是采集大量的執(zhí)行樣本進(jìn)行數(shù)學(xué)統(tǒng)計(jì)和分析
- 使用基礎(chǔ)基于
Benchmark.js
的 jsperf (或 jsbench)
慎用全局變量
- 全局變量定義在全局執(zhí)行上下文胧洒,是所有作用域鏈的頂端潮太, 后續(xù)使用的時(shí)候查找時(shí)間消耗大
- 全局變量上下文一直存在于上下文執(zhí)行棧,直到程序退出
- 如果某個(gè)局部作用域出現(xiàn)了同名變量則會(huì)遮蔽或污染全局
image.png
兩種情況對(duì)比,i
改成塊作用域局部變量,發(fā)現(xiàn)速度執(zhí)行變快糙及。
緩存全局變量
將使用中無(wú)法避免的全局變量緩存到局部
<body>
<button id="btn1">btn1</button>
<button id="btn2">btn2</button>
<button id="btn3">btn3</button>
<p>111</p>
<button id="btn4">btn4</button>
<button id="btn5">btn5</button>
<p>222</p>
<button id="btn6">btn6</button>
<p>333</p>
<button id="btn7">btn7</button>
<p>444</p>
<button id="btn8">btn8</button>
<button id="btn9">btn9</button>
<script>
function getBtn1() {
let btn1 = document.getElementById("btn1")
let btn3 = document.getElementById("btn3")
let btn5 = document.getElementById("btn5")
let btn7 = document.getElementById("btn7")
let btn9 = document.getElementById("btn9")
}
function getBtn2() {
let obj = document
let btn1 = obj.getElementById("btn1")
let btn3 = obj.getElementById("btn3")
let btn5 = obj.getElementById("btn5")
let btn7 = obj.getElementById("btn7")
let btn9 = obj.getElementById("btn9")
}
</script>
</body>
我們?cè)?code>getBtn2中,將document這個(gè)做了局部緩存筛欢,我們?cè)?code>jsbench中看一下運(yùn)行結(jié)果
image.png
通過(guò)原型鏈提升性能
在原型鏈上新增所需要的方法
image.png
我們發(fā)現(xiàn)速度提升了超過(guò)30%
避開(kāi)閉包陷阱
我們知道閉包使用不當(dāng)是可能會(huì)造成內(nèi)存泄露的
本質(zhì)上的做法就是當(dāng)我們使用完閉包后要將引用置為null
避免屬性訪問(wèn)方法
JavaScirpt中的面向?qū)ο?/p>
- JS不需屬性的訪問(wèn)方法浸锨,所有屬性都是外部可見(jiàn)的
-
使用屬性訪問(wèn)方法只會(huì)增加一層重定義,沒(méi)有訪問(wèn)的控制力
image.png
For循環(huán)優(yōu)化
image.png
這個(gè)過(guò)程中l(wèi)en 不需要多次計(jì)算就會(huì)節(jié)省運(yùn)行時(shí)間, 盡量減少循環(huán)體的活動(dòng)
選用最優(yōu)的循環(huán)方法
for
for...in
forEach
for...of
image.png
我們發(fā)現(xiàn)
forEach
的性能是最好的版姑,而其他三種性能基本類似
節(jié)點(diǎn)添加優(yōu)化
節(jié)點(diǎn)的添加操作必然會(huì)有重繪和回流
image.png
我們發(fā)現(xiàn)創(chuàng)建文檔碎片最后一期append的會(huì)更優(yōu)柱搜,并且節(jié)點(diǎn)數(shù)越多效果越明顯
使用克隆優(yōu)化節(jié)點(diǎn)操作
image.png
clone的效率明顯會(huì)高,并且操作的節(jié)點(diǎn)數(shù)越多剥险,效果越明顯
直接量替換new Object
image.png
但是這個(gè)場(chǎng)景不適合在基礎(chǔ)類型用使用 技術(shù)類型字面量會(huì)快很多
減少判斷層級(jí)
本質(zhì)就是在函數(shù)中不符合條件的提前返回 減少不必要的判斷
function foo(level) {
if (!level) {
return
}
if (level > 5) {
return
}
//符合條件邏輯
}
減少作用域鏈查找層級(jí)
let name = "old sam"
function foo() {
// name = "foo sam" 實(shí)際作用域?yàn)槿肿饔糜?僅僅在這里修改了值 當(dāng)bar里面取值的時(shí)候還是從全局找到了name
let name = "foo sam"
function bar() {
let age = 12
console.log(age)
console.log(name)
}
}
減少聲明以及語(yǔ)句數(shù)
image.png