喔唷网 - 网络从业者技术信息综合门户!

当前位置: 主页 > 教程技术 > 编程语言 > javascript

JavaScript 性能优化 让你的程序快如闪电

时间 : 2025-04-23 12:29来源 : 喔唷网作者 : 喔唷教程点击 :
各位性能调优师们,欢迎来到网站加速的秘密基地!本章我们将把慢吞吞的"乌龟网站"改造成敏捷的"猎豹应用"。准备好让你的代码起飞了吗? 14.1 代码优化技巧 - 给JavaScript"瘦身" 变量与作用域优化

各位性能调优师们,欢迎来到网站加速的秘密基地!本章我们将把慢吞吞的"乌龟网站"改造成敏捷的"猎豹应用"。准备好让你的代码起飞了吗?

14.1 代码优化技巧 - 给JavaScript"瘦身"

变量与作用域优化

// 坏味道
function processData(data) {
  let result = [];
  
  for (let i = 0; i < data.length; i++) {
    let item = data[i];
    let processedItem = doSomething(item);
    result.push(processedItem);
  }
  
  return result;
}

// 优化版
function processData(data) {
  return data.map(doSomething); // 简洁高效
}

循环优化实战

// 低效写法
const arr = [/* 大数组 */];
for (let i = 0; i < arr.length; i++) { // 每次读取length
  // ...
}

// 优化方案
for (let i = 0, len = arr.length; i < len; i++) { // 缓存length
  // ...
}

// 最佳方案
arr.forEach(item => { /*...*/ }); // 或者使用for...of

防抖与节流 - 控制函数调用频率

// 防抖:最后一次操作后等待执行
function debounce(fn, delay) {
  let timer;
  return function() {
    clearTimeout(timer);
    timer = setTimeout(() => fn.apply(this, arguments), delay);
  };
}

// 节流:固定时间间隔执行
function throttle(fn, interval) {
  let lastTime = 0;
  return function() {
    const now = Date.now();
    if (now - lastTime >= interval) {
      fn.apply(this, arguments);
      lastTime = now;
    }
  };
}

// 使用场景:滚动事件
window.addEventListener('scroll', throttle(handleScroll, 100));

14.2 内存管理 - 避免"内存泄漏"陷阱

常见内存泄漏场景

// 1. 意外的全局变量
function leak() {
  globalVar = '这是一个全局变量'; // 忘记var/let/const
}

// 2. 未清理的定时器
let timer = setInterval(() => {
  // 即使元素被移除了,定时器还在运行!
}, 1000);

// 正确做法
function cleanUp() {
  clearInterval(timer);
}

// 3. DOM引用未释放
const elements = {
  button: document.getElementById('myButton'),
  div: document.getElementById('myDiv')
};

function removeDiv() {
  document.body.removeChild(elements.div);
  // 即使移除了DOM,elements.div依然保持引用
}

内存优化实践

// WeakMap/WeakSet 允许被垃圾回收
const weakMap = new WeakMap();
let domNode = document.getElementById('node');
weakMap.set(domNode, '一些数据');

// 当domNode被移除后,weakMap中的条目会自动清除

14.3 加载性能优化 - 让页面秒开

资源加载策略

<!-- 延迟加载非关键JS -->
<script src="analytics.js" defer></script>

<!-- 预加载重要资源 -->
<link rel="preload" href="critical.css" as="style">
<link rel="prefetch" href="next-page-data.json" as="fetch">

<!-- 懒加载图片 -->
<img data-src="real-image.jpg" src="placeholder.jpg" 
     loading="lazy" alt="示例图片">

代码分割实战

// 动态导入实现按需加载
document.getElementById('btn').addEventListener('click', async () => {
  const module = await import('./heavy-module.js');
  module.doSomething();
});

// Webpack自动代码分割配置
// output: {
//   filename: '[name].[contenthash].bundle.js',
//   chunkFilename: '[name].[contenthash].chunk.js'
// }

14.4 渲染性能优化 - 60FPS的流畅体验

减少重排与重绘

// 糟糕的做法
function moveElement(element) {
  element.style.left = '100px'; // 重排
  element.style.top = '200px';  // 重排
  element.style.width = '300px'; // 重排
}

// 优化方案
function moveElement(element) {
  // 使用CSS类一次性修改
  element.classList.add('new-position');
}

// 或者使用requestAnimationFrame
function animate(element) {
  let pos = 0;
  function frame() {
    if (pos < 300) {
      pos++;
      element.style.left = pos + 'px';
      requestAnimationFrame(frame);
    }
  }
  requestAnimationFrame(frame);
}

虚拟列表优化长列表

class VirtualList {
  constructor(container, items, itemHeight) {
    this.container = container;
    this.items = items;
    this.itemHeight = itemHeight;
    this.visibleCount = Math.ceil(container.clientHeight / itemHeight);
    this.startIndex = 0;
    
    container.style.position = 'relative';
    container.style.overflow = 'auto';
    this.render();
    
    container.addEventListener('scroll', () => {
      this.startIndex = Math.floor(container.scrollTop / itemHeight);
      this.render();
    });
  }
  
  render() {
    // 只渲染可见项
    const endIndex = this.startIndex + this.visibleCount;
    const visibleItems = this.items.slice(this.startIndex, endIndex);
    
    // 更新容器高度
    this.container.style.height = `${this.items.length * this.itemHeight}px`;
    
    // 渲染可见项
    const fragment = document.createDocumentFragment();
    visibleItems.forEach((item, index) => {
      const div = document.createElement('div');
      div.style.position = 'absolute';
      div.style.top = `${(this.startIndex + index) * this.itemHeight}px`;
      div.textContent = item;
      fragment.appendChild(div);
    });
    
    this.container.innerHTML = '';
    this.container.appendChild(fragment);
  }
}

// 使用
new VirtualList(
  document.getElementById('list'),
  Array.from({length: 10000}, (_, i) => `Item ${i+1}`),
  50
);

本章总结

  1. 代码优化:精简逻辑,减少计算量
  2. 内存管理:及时清理,避免泄漏
  3. 加载优化:按需加载,预取资源
  4. 渲染优化:减少重排,高效更新

性能检测工具

  • Chrome DevTools Performance面板
  • Lighthouse综合评分
  • WebPageTest多地点测试
  • Memory面板检查内存泄漏

实战练习

  1. 分析你之前项目的性能瓶颈
  2. 实现图片懒加载组件
  3. 优化一个存在大量DOM操作的页面
  4. 使用Webpack进行代码分割

性能优化检查清单:

- [ ] 最小化JavaScript文件
- [ ] 使用Tree Shaking移除无用代码
- [ ] 压缩图片资源
- [ ] 启用Gzip/Brotli压缩
- [ ] 使用CDN分发静态资源
- [ ] 添加合适的缓存策略
- [ ] 减少第三方库依赖
- [ ] 避免同步布局抖动
- [ ] 使用CSS动画代替JS动画
- [ ] 实施代码分割和懒加载

下一章我们将深入调试与测试的世界,学习如何像侦探一样追踪bug!准备好你的放大镜了吗?

栏目列表

关联类容

热点推荐

栏目推荐

猜你喜欢