1. JS代码常见的性能问题
-
频繁的DOM访问:频繁地访问DOM元素可能会导致性能问题。因为访问DOM元素是非常昂贵的操作,它需要从浏览器中获取元素的引用并计算元素的位置和大小。
-
过多的HTTP请求:过多的HTTP请求会导致页面加载时间过长,从而影响用户体验。每次发送HTTP请求都需要建立TCP连接和传输数据,这些操作需要时间和资源。
-
大量的JavaScript文件:如果Web应用程序使用大量的JavaScript文件,那么加载时间会变得很长,从而影响用户体验。每个JavaScript文件都需要建立一个HTTP请求,并且需要解析和执行,这些操作都需要时间和资源。
-
内存泄漏:内存泄漏是指在代码中创建的对象无法被垃圾回收器正确地回收。如果JavaScript代码中存在内存泄漏,那么在长时间运行Web应用程序时,内存使用率可能会不断增加,从而导致性能问题
2. JavaScript性能优化技巧
为了解决JavaScript性能问题,我们需要采取一些优化措施。
2.1 减少重绘与重排
2.1.1 重绘与重排的概念
- 回流:也叫做重排,当我们对 DOM 的修改引发了 DOM 尺寸的变化时,浏览器需要重新计算元素的几何属性,其他元素的几何属性和位置也会因此受到影响,然后再将计算的结果绘制出来。这个过程就是回流
- 重绘:改变某个元素的背景色、文字颜色、边框颜色等等不影响它周围或内部布局的属性时,屏幕的一部分要重画,但是元素的几何尺寸没有变。这个过程就叫重绘
2.1.2 方法
- css:
- 避免使用table布局。
- 尽可能在DOM树的最末端改变class。
- 避免设置多层内联样式。
- 将动画效果应用到position属性为absolute或fixed的元素上。
- 避免使用CSS表达式。
- js
- 最好一次性重写style属性,或者将样式列表定义为class并一次性更改class属性。
- 避免频繁操作DOM,创建一个documentFragment,在它上面应用所有DOM操作,最后再把它添加到文档中。
- 也可以先为元素设置display: none,操作结束后再把它显示出来。因为在display属性为none的元素上进行的DOM操作不会引发回流和重绘。
- 具有复杂动画的元素使用绝对定位,使它脱离文档流
2.2 节流和防抖技术
2.2.1 节流与防抖的概念
- 函数防抖:将几次操作合并为一次操作进行。原理是维护一个计时器,规定在delay时间后触发函数,但是在delay时间内再次触发的话,就会取消之前的计时器而重新设置。这样一来,只有最后一次操作能被触发。
- 函数节流:使得一定时间内只触发一次函数。原理是通过判断是否到达一定时间来触发函数。
2.2.2 方法
- 节流
- 持续触发scroll事件时,并不执行handle函数,当1000毫秒内没有触发scroll事件时,才会延时触发scroll事件。
function debounce(fn, wait) {
var timeout = null;
return function() {
if(timeout !== null) clearTimeout(timeout);
timeout = setTimeout(fn, wait);
}
}
// 处理函数
function handle() {
console.log(Math.random());
}
// 滚动事件
window.addEventListener('scroll', debounce(handle, 1000));
- 防抖
- 持续触发scroll事件时,并不立即执行handle函数,每隔1000毫秒才会执行一次handle函数。
var throttle = function(func, delay) {
var prev = Date.now();
return function() {
var context = this;
var args = arguments;
var now = Date.now();
if (now - prev >= delay) {
func.apply(context, args);
prev = Date.now();
}
}
}
function handle() {
console.log(Math.random());
}
window.addEventListener('scroll', throttle(handle, 1000));
二者区别
函数节流不管事件触发有多频繁,都会保证在规定时间内一定会执行一次真正的事件处理函数,而函数防抖只是在最后一次事件后才触发一次函数。比如在页面的无限加载场景下,我们需要用户在滚动页面时,每隔一段时间发一次 Ajax 请求,而不是在用户停下滚动页面操作时才去请求数据。这样的场景,就适合用节流技术来实现。
2.3 使用性能分析工具
对于前端开发人员来说,除了实现页面功能外,那就是页面的性能响应问题也要关注。同样对于测试人员在进行性能测试时,也要关注前端页面的性能指标。测试前端性能市面上可以用到的工具也比较多,比如可以用 HttpWatch 进行页面的抓取与分析,或者也可以使用抓包工具如 Fiddler 抓接口的形式进行分析。
2.3.1 JSBench
根据官方的介绍Jsbench.me 是一个JavaScript的性能基准测试平台,深受 jsperf.com 和 jsfiddle.net 的启发和影响。 它使用 Benchmarkjs.com 来执行测试套件
2.3.1.1 使用建议
-
使用性能测试的时候,建议浏览器只打开一个标签页,因为开启过多标签页会抢占资源,测试结果不那么准确。
-
还有就是在运行的时候尽量保持在这个页面上,不要什么最小化页面去做别的事情,因为有可能会被我们的系统挂起,那么测试的结果不一定准确。
-
不能执行完一遍之后得到的结论就觉得是最终的答案,应该多执行几次取出现几率最高的结果。
-
不应该纠结于代码的执行时间,对于性能测试而言,关注的并不是只有时间。