JavaScript性能优化

2020-08-09  本文已影响0人  zxhnext

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>
image.png

通过原型对象添加附加方法
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()
image.png

避开闭包陷阱

● 闭包是一种强大的语法
● 闭包使用不当很容易出现内存泄露
● 不要为了闭包而闭包

demo:

function test(func) {
    console.log(func())
}

function test2() {
    var name = 'lg'
    return name
}

test(function() { // 属于闭包,内部有赋值操作
    var name = 'lg'
    return name
})

test(test2)
image.png

避免属性访问方法使用

● 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
image.png

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])
}
image.png

选择最优的循环方法
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)
}
image.png

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)
image.png

克隆优化节点操作
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>
image.png

直接量替换 new Object
demo:

let a = [1, 2, 3]

let a1 = new Array(1, 2, 3)
image.png
上一篇下一篇

猜你喜欢

热点阅读