JavaScript性能优化

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
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,080评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,422评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,630评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,554评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,662评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,856评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,014评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,752评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,212评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,541评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,687评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,347评论 4 331
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,973评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,777评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,006评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,406评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,576评论 2 349