1. 如何精準(zhǔn)測(cè)試 JavaScript 性能
● 本質(zhì)上就是采集大量的執(zhí)行樣本進(jìn)行數(shù)學(xué)統(tǒng)計(jì)和分析
● 使用基于 Benchmark.js 的 https://jsperf.com/ 完成
1.1 Jsperf使用流程
● 使用GitHub賬號(hào)登錄
● 填寫個(gè)人信息(非必須)
● 填寫詳細(xì)的測(cè)試用例信息( title根悼、 slug)
● 填寫準(zhǔn)備代碼(DOM操作時(shí)經(jīng) 常使用)
● 填寫必要有setup與teardown代碼
● 填寫測(cè)試代碼片段
2.1 慎用全局變量
● 全局變量定義在全局執(zhí)行上下文,是所有作用域鏈的頂端(查找消耗時(shí)間)
● 全局執(zhí)行上下文一直存在于上下文執(zhí)行棧母廷,直到程序退出(不利于GC)
● 如果某個(gè)局部作用域出現(xiàn)了同名變量則會(huì)遮蔽或污染全局
2.2 緩存全局變量
將使用中無(wú)法避免的全局變量緩存到局部
demo:
<input type="button" value="btn" id="btn1" />
<input type="button" value="btn" id="btn2" />
<input type="button" value="btn" id="btn3" />
<input type="button" value="btn" id="btn4" />
<p>1111</p>
<input type="button" value="btn" id="btn5" />
<input type="button" value="btn" id="btn6" />
<p>2222</p>
<input type="button" value="btn" id="btn7" />
<input type="button" value="btn" id="btn8" />
<input type="button" value="btn" id="btn9" />
<p>3333</p>
<input type="button" value="btn" id="btn10" />
<script>
function getBtn() {
let oBtn1 = document.getElementById('btn1')
let oBtn3 = document.getElementById('btn3')
let oBtn5 = document.getElementById('btn5')
let oBtn7 = document.getElementById('btn7')
let oBtn9 = document.getElementById('btn9')
}
function getBtn2() {
let obj = document
let oBtn1 = obj.getElementById('btn1')
let oBtn3 = obj.getElementById('btn3')
let oBtn5 = obj.getElementById('btn5')
let oBtn7 = obj.getElementById('btn7')
let oBtn9 = obj.getElementById('btn9')
}
</script>
通過(guò)原型對(duì)象添加附加方法
demo:
var fn1 = function() {
this.foo = function() {
console.log(1111)
}
}
let f1 = new fn1()
var fn2 = function() {
}
fn2.prototype.foo = function() {
console.log(1111)
}
let f2 = new fn2()
避開閉包陷阱
● 閉包是一種強(qiáng)大的語(yǔ)法
● 閉包使用不當(dāng)很容易出現(xiàn)內(nèi)存泄露
● 不要為了閉包而閉包
demo:
function test(func) {
console.log(func())
}
function test2() {
var name = 'lg'
return name
}
test(function() { // 屬于閉包,內(nèi)部有賦值操作
var name = 'lg'
return name
})
test(test2)
避免屬性訪問方法使用
● JS不需屬性的訪問方法蓄髓,所有屬性都是外部可見的
● 使用屬性訪問方法只會(huì)增加一層重定義,沒有訪問的控制力
demo:
function Person() {
this.name = 'lg'
this.age = 18
this.getAge = function() {
return this.age
}
}
const p1 = new Person()
const a = p1.getAge()
function Person() {
this.name = 'lg'
this.age = 18
}
const p2 = new Person()
const b = p2.age
for循環(huán)優(yōu)化
demo:
var arrList = []
arrList[10000] = 'lg'
for (let i = 0; i < arrList.length; i++) {
console.log(arrList[i])
}
for (var i = arrList.length; i; i--) {
console.log(arrList[i])
}
選擇最優(yōu)的循環(huán)方法
demo:
let arrList = new Array(1, 2, 3, 4, 5)
arrList.forEach(item => {
console.log(item)
})
for (let i = arrList.length; i; i--) {
console.log(arrList[i])
}
for (let i in arrList) {
console.log(arrList[i])
}
for (let item of arrList) {
console.log(item)
}
forEach比f(wàn)or循環(huán)快的原因:
[1,2, ,3] arr.forEach(() => {
// 這里每次開啟一個(gè)作用域
})
for (let i = arr.length; i >= 0; i--) {
// 開啟兩個(gè)作用域,這里一個(gè)鹉梨,括號(hào)里一個(gè)
}
文檔碎片優(yōu)化節(jié)點(diǎn)開發(fā)
節(jié)點(diǎn)的添加操作必然有回流和重繪
demo:
for (let i = 0; i < 10; i++) {
let oP = document.createElement('p')
oP.innerHTML = i
document.body.appendChild(oP)
}
const fragEle = document.createDocumentFragment()
for (let i = 0; i < 10; i++) {
let oP = document.createElement('p')
oP.innerHTML = i
fragEle.appendChild(oP)
}
document.body.appendChild(fragEle)
克隆優(yōu)化節(jié)點(diǎn)操作
demo:
<p id="box1">old</p>
<script>
for (let i = 0; i < 5; i++) {
let oP = document.createElement('p')
oP.innerHTML = i
document.body.appendChild(oP)
}
let oldP = document.getElementById('box1')
for (let i = 0; i < 5; i++) {
let newP = oldP.cloneNode(false)
newP.innerHTML = i
document.body.appendChild(newP)
}
</script>
直接量替換 new Object
demo:
let a = [1, 2, 3]
let a1 = new Array(1, 2, 3)