1. 如何精准测试 JavaScript 性能
● 本质上就是采集大量的执行样本进行数学统计和分析
● 使用基于 Benchmark.js 的 https://jsperf.com/ 完成
1.1 Jsperf使用流程
● 使用GitHub账号登录
● 填写个人信息(非必须)
● 填写详细的测试用例信息( title、 slug)
● 填写准备代码(DOM操作时经 常使用)
● 填写必要有setup与teardown代码
● 填写测试代码片段
2.1 慎用全局变量
● 全局变量定义在全局执行上下文,是所有作用域链的顶端(查找消耗时间)
● 全局执行上下文一直存在于上下文执行栈,直到程序退出(不利于GC)
● 如果某个局部作用域出现了同名变量则会遮蔽或污染全局
2.2 缓存全局变量
将使用中无法避免的全局变量缓存到局部
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>
通过原型对象添加附加方法
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()
避开闭包陷阱
● 闭包是一种强大的语法
● 闭包使用不当很容易出现内存泄露
● 不要为了闭包而闭包
demo:
function test(func) {
console.log(func())
}
function test2() {
var name = 'lg'
return name
}
test(function() { // 属于闭包,内部有赋值操作
var name = 'lg'
return name
})
test(test2)
避免属性访问方法使用
● JS不需属性的访问方法,所有属性都是外部可见的
● 使用属性访问方法只会增加一层重定义,没有访问的控制力
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循环优化
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])
}
选择最优的循环方法
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比for循环快的原因:
[1,2, ,3] arr.forEach(() => {
// 这里每次开启一个作用域
})
for (let i = arr.length; i >= 0; i--) {
// 开启两个作用域,这里一个,括号里一个
}
文档碎片优化节点开发
节点的添加操作必然有回流和重绘
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)
克隆优化节点操作
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)