JavaScript 性能优化实战

JavaScript性能优化技巧

JavaScript性能优化实战 10w+人浏览 425人参与

减少重绘和回流

频繁操作 DOM 会导致浏览器反复计算布局,触发重绘和回流。使用 documentFragment 进行批量 DOM 操作,或通过修改 className 一次性应用样式变更。对复杂动画元素使用 transformopacity 属性,这些属性由合成器线程处理,不会触发主线程布局计算。

// 使用 documentFragment 减少回流
const fragment = document.createDocumentFragment();
for (let i = 0; i < 100; i++) {
  const div = document.createElement('div');
  fragment.appendChild(div);
}
document.body.appendChild(fragment);

事件委托优化

避免为大量子元素单独绑定事件监听器。利用事件冒泡机制,在父元素上统一处理事件。通过 event.target 识别实际触发元素,减少内存占用和初始化时间。

// 事件委托示例
document.getElementById('parent').addEventListener('click', function(e) {
  if (e.target.classList.contains('child')) {
    handleChildClick(e.target);
  }
});

内存管理

及时清除不再使用的定时器、事件监听器和对象引用。使用 WeakMapWeakSet 存储临时数据,避免内存泄漏。对于大型数据集,采用惰性加载或分页加载策略。

// 清除无效引用
const obs = new IntersectionObserver(callback);
obs.disconnect(); // 不再需要时断开观察

// 使用 WeakMap 避免内存泄漏
const wm = new WeakMap();
wm.set(document.getElementById('temp'), {data: largeObject});

代码分割与懒加载

利用动态 import() 语法实现路由级或组件级代码分割。配合 webpack 的 splitChunks 配置,将第三方库分离到独立 chunk。对于非首屏关键资源,使用 IntersectionObserver 实现懒加载。

// 动态导入组件
const HeavyComponent = () => import('./HeavyComponent.vue');

// 图片懒加载
const observer = new IntersectionObserver((entries) => {
  entries.forEach(entry => {
    if (entry.isIntersecting) {
      entry.target.src = entry.target.dataset.src;
      observer.unobserve(entry.target);
    }
  });
});

Web Worker 应用

将 CPU 密集型任务(如数据处理、图像计算)转移到 Web Worker 线程。注意 worker 与主线程通信存在序列化开销,批量传输数据优于频繁小消息。

// 主线程
const worker = new Worker('task.js');
worker.postMessage(largeData);
worker.onmessage = (e) => processResults(e.data);

// worker.js
self.onmessage = (e) => {
  const result = compute(e.data);
  self.postMessage(result);
};

性能监测工具

使用 Performance API 进行精确测量,结合 Chrome DevTools 的 Performance 面板分析运行时瓶颈。监控关键指标:首次内容绘制(FCP)、最大内容绘制(LCP)、输入延迟(INP)。

// 测量代码执行时间
performance.mark('start');
// 执行代码...
performance.mark('end');
performance.measure('task', 'start', 'end');
console.log(performance.getEntriesByName('task')[0].duration);

节流与防抖优化

对于高频触发事件(scroll、resize、input),使用防抖(debounce)或节流(throttle)控制执行频率。Lodash 的实现经过充分优化,可直接引用相关函数。

// 滚动事件节流
window.addEventListener('scroll', _.throttle(() => {
  updatePosition();
}, 100));

// 搜索框防抖
searchInput.addEventListener('input', _.debounce(() => {
  fetchResults();
}, 300));

缓存策略应用

对计算结果进行缓存,避免重复计算。使用 Map 或对象存储函数结果,对于纯函数可实施 memoization 模式。Service Worker 可用于缓存网络请求。

// 记忆化函数
const memoize = (fn) => {
  const cache = new Map();
  return (...args) => {
    const key = JSON.stringify(args);
    if (cache.has(key)) return cache.get(key);
    const result = fn(...args);
    cache.set(key, result);
    return result;
  };
};

避免微任务堆积

Promise 回调、MutationObserver 等微任务会在当前任务结束后立即执行。避免在循环中创建大量微任务,这会导致主线程被阻塞无法处理用户交互。

// 优化前:同步产生大量微任务
function processItems(items) {
  items.forEach(item => {
    Promise.resolve().then(() => handleItem(item));
  });
}

// 优化后:批量处理
async function processItems(items) {
  for (const item of items) {
    await handleItem(item);
  }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值