JavaScript 性能优化与调试技巧| 豆包MarsCode AI刷题

90 阅读4分钟

一、减少重绘和重排

(一)理解重绘和重排

  1. 重排(Reflow)

    • 定义:当 DOM 的几何属性(如宽、高、边距、位置等)发生变化时,浏览器需要重新计算元素的几何属性,并重新布局页面,这个过程称为重排。

    • 常见触发重排的操作:

      • 改变元素的尺寸:例如设置widthheightmarginpadding等属性。
      • 改变元素的位置:例如设置lefttoprightbottom等属性。
      • 改变浏览器窗口大小或字体大小。
      • 添加或删除 DOM 节点。
  2. 重绘(Repaint)

    • 定义:当元素的外观(如颜色、背景色等)发生改变,但不影响布局时,浏览器只需要重新绘制元素的外观,这个过程称为重绘。

    • 常见触发重绘的操作:

      • 改变元素的颜色:例如设置colorbackground - color等属性。
      • 改变元素的不透明度:例如设置opacity属性。

(二)减少重绘和重排的策略

  1. 合并样式更改
  • 示例:

  • 不好的做法:

// 多次更改样式,会多次触发重排和重绘
element.style.width = '100px';
element.style.height = '100px';
element.style.backgroundColor = 'red';
  • 好的做法:

// 使用CSS类名或一次性更改样式
element.className = 'new - class';
// 或者使用CSSOM的方式
var style = element.style;
style.cssText = 'width: 100px; height: 100px; background - color: red;';
  1. 将 DOM 操作离线处理
  • 使用DocumentFragment

  • 示例:

// 创建DocumentFragment
var fragment = document.createDocumentFragment();
for (var i = 0; i < 10; i++) {
  var li = document.createElement('li');
  li.textContent = 'Item'+ i;
  fragment.appendChild(li);
}
// 一次性将DocumentFragment中的内容添加到DOM中
document.getElementById('list').appendChild(fragment);
  • 使用display: none

  • 示例:

// 先隐藏元素
element.style.display = 'none';
// 进行大量DOM操作
//...
// 操作完成后再显示元素
element.style.display = '';
  1. 避免频繁访问布局信息
  • 不好的做法:
// 每次循环都获取元素的高度,会导致多次重排
for (var i = 0; i < 10; i++) {
  var height = element.offsetHeight;
  //...
}
  • 好的做法:

// 先获取布局信息,再进行操作
var height = element.offsetHeight;
for (var i = 0; i < 10; i++) {
  // 使用之前获取的高度
  //...
}

二、使用节流和防抖技术

(一)节流(Throttle)

  1. 定义

    • 节流是指在一定时间内,只允许函数执行一次。例如,在滚动事件中,如果不进行节流处理,函数可能会在短时间内被频繁调用,通过节流可以限制函数的调用频率。
  2. 实现示例

function throttle(func, delay) {
  let timer = null;
  return function() {
    if (!timer) {
      func.apply(this, arguments);
      timer = setTimeout(() => {
        timer = null;
      }, delay);
    }
  };
}
// 使用示例
window.addEventListener('scroll', throttle(() => {
  console.log('Scrolled');
}, 200));

(二)防抖(Debounce)

  1. 定义

    • 防抖是指在事件被触发后,延迟一定时间再执行回调函数,如果在延迟时间内事件再次被触发,则重新计算延迟时间。常用于搜索框输入事件等,避免频繁发送请求。
  2. 实现示例

function debounce(func, delay) {
  let timer = null;
  return function() {
    if (timer) {
      clearTimeout(timer);
    }
    timer = setTimeout(() => {
      func.apply(this, arguments);
    }, delay);
  };
}
// 使用示例
var input = document.getElementById('search - input');
input.addEventListener('input', debounce(() => {
  console.log('Search input:', input.value);
}, 300));

三、使用性能分析工具

(一)浏览器自带的性能工具

  1. Chrome DevTools

    • Timeline(时间轴)

      • 功能:可以记录和可视化页面加载过程中的各种事件,包括 JavaScript 执行、DOM 事件、布局和绘制等。通过时间轴可以发现性能瓶颈,例如长时间的脚本执行或频繁的重排重绘。

      • 使用方法:

        • 打开 Chrome 浏览器,按F12打开开发者工具。
        • 选择Timeline选项卡。
        • 点击Record按钮开始记录,然后在页面上进行操作,操作完成后点击Stop按钮。
        • 分析时间轴上的记录,查看耗时较长的操作。
    • Performance(性能)

      • 功能:提供更详细的性能分析,包括 CPU 使用率、内存占用等。可以对 JavaScript 函数进行采样分析,查看函数的执行时间和调用频率。

      • 使用方法:

        • 打开 Chrome 开发者工具,选择Performance选项卡。
        • 点击Record按钮开始记录,进行页面操作后停止记录。
        • 在分析结果中查看各种性能指标和函数调用情况。

(二)第三方性能分析工具

  1. Lighthouse

    • 功能:是一个开源的自动化工具,用于改进网页的质量。它可以对页面的性能、可访问性、最佳实践、搜索引擎优化(SEO)等方面进行评估,并给出改进建议。

    • 使用方法:

      • 在 Chrome 浏览器中,打开开发者工具,选择Lighthouse选项卡。
      • 选择要分析的类别(如性能),然后点击Generate report按钮。
      • 根据报告中的建议进行优化。
  2. WebPageTest

    • 功能:是一个在线的网页性能测试工具,可以从多个地点和浏览器对网页进行测试,提供详细的性能指标和优化建议,包括页面加载时间、首次字节时间(TTFB)、渲染开始时间等。

    • 使用方法:

      • 访问https://www.webpagetest.org/

      • 输入要测试的网址,选择测试地点、浏览器等参数。

      • 点击Start Test按钮,等待测试结果。

      • 分析测试报告,根据建议进行优化。

通过以上这些 JavaScript 性能优化和调试技巧,可以有效地提高网页的性能,提升用户体验。