JS性能优化 —— JS代码优化

2,384 阅读3分钟

目录

  • 性能测试工具的介绍
    • 使用流程
  • JS代码优化
    • 慎用全局变量
    • 缓存全局变量
    • 通过原型新增方法
    • 避开闭包陷阱
    • 避免属性访问方法使用
    • for循环优化
    • 选择最优的循环方法
    • 节点添加优化
    • 克隆优化节点操作
    • 直接量替换 new Object

性能测试工具的介绍

性能工具可以辅助我们知道如何写代码是更高效的,其本质上就是采集大量的执行样本进行数学统计和分析。

  • 使用基于Benchmark.jsjsperf.com 完成,目前这个网站一直502,感兴趣可以本地部署npm i benchmark --save-dev一下瞅瞅
  • 代替网站可以使用 jsbench.me

使用流程(因为一直502目前没有使用过)

  • 登录
  • 填写详细的测试用例信息(title/ slug是短名称,会生成一个网址,因此不可与别人的重复。)
  • 填写准备代码(DOM操作时经常使用)
  • 填写必要有setup(启动操作)与 teardown(执行完成后销毁操作)代码

JS代码优化

代码优化的种类很多,先简单介绍几个,这也是一个积累的过程,以后有遇到的就在这里面增加

慎用全局变量

为什么要慎用?

  • 全局变量定义在全局执行上下文,是所有作用域链的顶端。每次查找的时候都从局部找到最顶端,时间会有所消耗
  • 全局执行上下文一直存在于上下文执行栈,直到程序退出,内存空间浪费
  • 如果某个局部作用域出现了同名变量则会遮蔽或污染全局

下图不看功能,只是想说明用全局变量和不用全局变量的差别:

缓存全局变量

将使用中无法避免的全局变量缓存到局部,下面可以看到缓存过的比没有缓存过的性能要有所提高。

通过原型新增方法

尽量在原型对象上新增实例对象需要的方法,而不是在构造函数内部添加方法。

避开闭包陷阱

闭包可以在外部作用域访问函数内部作用域的数据。

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

实例分析

下面代码形成了一个闭包,el存在foo函数的作用域里面,而onclick指向的匿名函数又是一个新的作用域,里面引用了foo作用域中的id,会导致内存泄露。

function foo() {
    var el = document.getElementById('btn')
    el.onclick = function() {
        console.log(el.id)
    }
}

foo()

想要内存不泄露,使用完之后将el置为null

function foo() {
	// 等号右边的代码本来就存在于`DOM`树上,`el`是一个新的引用。
    // 这个元素被我们引用了两次。就算`DOM`被`remove`掉了,但是代码`el`中也会引用,只能在下面把代码进行手动清除。
    var el = document.getElementById('btn')
    el.onclick = function() {
        console.log(el.id)
    }
    
    // 如果想要不泄露,就添加下面这个
    el = null
}

foo()

避免属性访问方法使用

JavaScript中的面向对象中

  • JS不需要属性的访问方法,所有属性都是外部可见的
  • 属性访问方法只会增加一层重定义,没有访问的控制力

for循环优化

把数组的length也存放到一个变量上。

选择最优的循环方法

forEachforfor-in的比较

节点添加优化

节点的添加操作必然会有回流和重绘

document.createdocumentfragment()方法创建了一虚拟的节点对象,是一段新的文档片段,该对象包含所有属性和方法。
这样可以合并节点的添加操作,减少DOM的重绘。

克隆优化节点操作

已经有的属性和内容不用再次添加

直接量替换 new Object

当我们定义对象和数组的时候,我们可以用new,也可以采用字面量。