性能优化与调试技巧 | 青训营

50 阅读5分钟

1. JS代码常见的性能问题

  1. 频繁的DOM访问:频繁地访问DOM元素可能会导致性能问题。因为访问DOM元素是非常昂贵的操作,它需要从浏览器中获取元素的引用并计算元素的位置和大小。

  2. 过多的HTTP请求:过多的HTTP请求会导致页面加载时间过长,从而影响用户体验。每次发送HTTP请求都需要建立TCP连接和传输数据,这些操作需要时间和资源。

  3. 大量的JavaScript文件:如果Web应用程序使用大量的JavaScript文件,那么加载时间会变得很长,从而影响用户体验。每个JavaScript文件都需要建立一个HTTP请求,并且需要解析和执行,这些操作都需要时间和资源。

  4. 内存泄漏:内存泄漏是指在代码中创建的对象无法被垃圾回收器正确地回收。如果JavaScript代码中存在内存泄漏,那么在长时间运行Web应用程序时,内存使用率可能会不断增加,从而导致性能问题

2. JavaScript性能优化技巧

为了解决JavaScript性能问题,我们需要采取一些优化措施。

2.1 减少重绘与重排

2.1.1 重绘与重排的概念

  • 回流:也叫做重排,当我们对 DOM 的修改引发了 DOM 尺寸的变化时,浏览器需要重新计算元素的几何属性,其他元素的几何属性和位置也会因此受到影响,然后再将计算的结果绘制出来。这个过程就是回流
  • 重绘:改变某个元素的背景色、文字颜色、边框颜色等等不影响它周围或内部布局的属性时,屏幕的一部分要重画,但是元素的几何尺寸没有变。这个过程就叫重绘

2.1.2 方法

  1. css:
  • 避免使用table布局。
  • 尽可能在DOM树的最末端改变class。
  • 避免设置多层内联样式。
  • 将动画效果应用到position属性为absolute或fixed的元素上。
  • 避免使用CSS表达式。
  1. js
  • 最好一次性重写style属性,或者将样式列表定义为class并一次性更改class属性。
  • 避免频繁操作DOM,创建一个documentFragment,在它上面应用所有DOM操作,最后再把它添加到文档中。
  • 也可以先为元素设置display: none,操作结束后再把它显示出来。因为在display属性为none的元素上进行的DOM操作不会引发回流和重绘。
  • 具有复杂动画的元素使用绝对定位,使它脱离文档流

2.2 节流和防抖技术

2.2.1 节流与防抖的概念

  • 函数防抖:将几次操作合并为一次操作进行。原理是维护一个计时器,规定在delay时间后触发函数,但是在delay时间内再次触发的话,就会取消之前的计时器而重新设置。这样一来,只有最后一次操作能被触发。
  • 函数节流:使得一定时间内只触发一次函数。原理是通过判断是否到达一定时间来触发函数。

2.2.2 方法

  1. 节流
  • 持续触发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));
  1. 防抖
  • 持续触发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 使用建议

  • 使用性能测试的时候,建议浏览器只打开一个标签页,因为开启过多标签页会抢占资源,测试结果不那么准确。

  • 还有就是在运行的时候尽量保持在这个页面上,不要什么最小化页面去做别的事情,因为有可能会被我们的系统挂起,那么测试的结果不一定准确。

  • 不能执行完一遍之后得到的结论就觉得是最终的答案,应该多执行几次取出现几率最高的结果。

  • 不应该纠结于代码的执行时间,对于性能测试而言,关注的并不是只有时间。