了解JS性能优化是学习前端必备的一项技能。下面我们来总结js性能优化方法:
1.注意作用域,避免全局查找。
访问全局变量比访问局部变量慢,是因为需要遍历作用域链,查找作用域链需要额外的时间。所以在一个函数中,将访问多次的全局对象或者域外变量存储为局部变量来使用。如某个方法需引用全局变量的值,则在该方法所在的对象的作用域中定义一个局部变量等于全局变量的值。
避免不必要的属性查找,将属性设置为局部变量。
function(){
var title = document.title;
for(var i=0;i<3;i++){
console.log(title);
}
}
2.优化循环
简化循环体。当循环的数量不多时,展开循环。当if-else较多时,建议使用switch语句。
3.最小化语句数
声明多个变量时,可以使用一个var关键字来声明,变量之间用逗号表示。
使用数组或对象字面量来新建数组或对象。var arr= [1,2,3,4];var map={a:1,b:2}
4.JS的执行尽量脱离DOM树,限制DOM操作的次数,优化DOM交互,尽量减少浏览器对DOM的渲染和重绘操作
最小化现场更新,现场更新就是立即对页面的显示进行更新。尽量少更新。这时候可使用文档碎片来构建DOM结构。document.createDocumentFragment()
使用innerHTML来构建大的DOM结构。但是也避免重复大量的使用。
5.使用事件代理
页面上的事件处理程序的数量和页面响应用户交互的速度之间有个负相关。所以为了减少事件处理程序,尽量使用事件委托技术。
6.JS的执行顺序
JS放HTML页面最后面时,不一定提升JS性能,但是在网速较慢的时候会快速的渲染页面。
7.JS定义行为,html定义内容,CSS定义外观,不混淆
8.减少HTTP请求数,JS压缩,HTTP压缩
9.数据尽量存储在数组里
10、代码的优化不是减少代码量,而是增加代码提高代码的可阅读性。
包括正确标记变量,封装某个重复的行为,合理的注释等。
11.避免过多的重排与重绘操作。
尽量将DOM中的多个读操作放一起,中间不要插入写的操作,因为写操作会导致浏览器迅速的重排,从而影响性能。将DOM中的多个写操作放一起,不要插入读的操作,如果插入读操作会导致浏览器多次重排。也就是DOM中读写操作分开。
12.缓存重排获取的值
避免下次用到该值的时候,浏览器又需要重排。
13.通过设置样式名来修改元素样式
通过改变元素的class,或者csstext属性来改变元素的样式。
14.尽量使用离线DOM来操作节点
例如操作Document Fragment对象,完成后把这个对象插入到实际的DOM中。或者cloneNode()方法,在克隆的节点上操作,再用克隆的节点替换原节点。
15.对操作频繁的元素使用display:none,然后对其操作,操作完后恢复显示display:block
这样处理的话,浏览器相当于渲染页面只有两次(隐藏或显示)。不可见的元素不影响重排或重绘。
16.将元素设为position:fixed或absolute,重排的开销会很小
因为被定位的元素不会影响其他元素的布局。
17.使用虚拟DOM的脚本库
比如React等。
18.使用window.requestAnimationFrame(),window.requestIdleCallback()
这两个方法调节重新渲染。
requestAnimationFrame(func),传一个函数进去当作参数,这个函数是一个屏幕重绘前被调用的函数,等下次浏览器渲染时执行函数里的操作。其实这个跟setTimeout()类似,只是间隔时间是由浏览器自己(下次渲染)来决定。这个方法解决了浏览器不知道Javascript动画正在执行和不知道多少才是合适的间隔的问题。
兼容写法:mozRequestAnimationFrame() || msRequestAnimationFrame() || weibkitRequestAnimationFrame() || oRequestAnimationFrame()
使用场景比如:重复执行的函数,JS动画(滑动),页面滚动,页面放大缩小等。
案例:
<script>
function scroll(elem){
var hei = elem.clientHeight;
window.requestAnimationFrame(function(){
elem.style.height = (hei*2) + 'px';
})
}
function scroll2(elem){
var hei = elem.clientHeight;
elem.style.height = (hei*2) + 'px';
}
elem = document.getElementById('elem');
console.time('a');
for(var i=0;i<100000;i++){
scroll(elem);
}
console.timeEnd('a');
console.time('b');
for(var i=0;i<100000;i++){
scroll2(elem);
}
console.timeEnd('b');
</script>
log里输出:
a: 389.112ms
b: 3922.486ms
很明显,使用requestAnimationFrame()方法后执行更有效率。不过该方法也有兼容性问题,是否使用还得看项目而定。