性能优化与内存管理
性能优化提升用户体验,内存管理保证应用稳定运行。
渲染性能优化
重排与重绘
| 操作 | 影响 |
|---|---|
| 重排 | 改变元素几何属性,重新计算布局 |
| 重绘 | 改变元素外观,不影响布局 |
JavaScript
// 批量修改DOM - 减少重排
const fragment = document.createDocumentFragment();
items.forEach(item => {
fragment.appendChild(createElement(item));
});
container.appendChild(fragment);
使用 requestAnimationFrame
JavaScript
// 动画使用rAF
function animate() {
updatePosition();
requestAnimationFrame(animate);
}
requestAnimationFrame(animate);
// 避免使用setInterval做动画
// setInterval(update, 16); // 不推荐
虚拟列表
JavaScript
// 只渲染可视区域元素
const visibleStart = Math.floor(scrollTop / itemHeight);
const visibleEnd = visibleStart + visibleCount;
const visibleItems = items.slice(visibleStart, visibleEnd);
render(visibleItems);
JavaScript 执行优化
防抖与节流
JavaScript
// 防抖 - 停止触发后执行
function debounce(fn, delay) {
let timer;
return function(...args) {
clearTimeout(timer);
timer = setTimeout(() => fn.apply(this, args), delay);
};
}
// 节流 - 固定间隔执行
function throttle(fn, limit) {
let inThrottle;
return function(...args) {
if (!inThrottle) {
fn.apply(this, args);
inThrottle = true;
setTimeout(() => inThrottle = false, limit);
}
};
}
代码分割与懒加载
JavaScript
// 动态import
button.addEventListener('click', async () => {
const module = await import('./heavy-module.js');
module.doSomething();
});
// Intersection Observer懒加载
const observer = new IntersectionObserver(entries => {
entries.forEach(entry => {
if (entry.isIntersecting) {
entry.target.src = entry.target.dataset.src;
observer.unobserve(entry.target);
}
});
});
images.forEach(img => observer.observe(img));
内存管理
垃圾回收机制
JavaScript使用标记清除算法:
- 从根对象开始标记
- 标记所有可达对象
- 清除未标记对象
常见内存泄漏
JavaScript
// 1. 全局变量
function leak() {
bar = 'global'; // 意外全局变量
}
// 2. 未清理的定时器
const timer = setInterval(() => {}, 1000);
// 忘记 clearInterval(timer)
// 3. 闭包引用
function createClosure() {
const largeData = new Array(10000);
return function() {
console.log(largeData.length); // 持有引用
};
}
// 4. DOM引用
const elements = [];
document.getElementById('btn').addEventListener('click', () => {});
// 即使移除DOM,elements仍持有引用
避免内存泄漏
JavaScript
// 及时清理定时器
const timer = setInterval(callback, 1000);
// 组件销毁时
clearInterval(timer);
// 使用WeakMap避免强引用
const cache = new WeakMap();
cache.set(element, data);
// element被移除时自动释放
// 移除事件监听
element.addEventListener('click', handler);
// 销毁时
element.removeEventListener('click', handler);
// 闭包只保留需要的数据
function createHandler(id) {
// 只保存id,不保存整个对象
return () => console.log(id);
}
性能监控
Performance API
JavaScript
// 页面加载性能
const timing = performance.timing;
const loadTime = timing.loadEventEnd - timing.navigationStart;
// 使用PerformanceObserver
const observer = new PerformanceObserver(list => {
list.getEntries().forEach(entry => {
console.log(entry.name, entry.duration);
});
});
observer.observe({ entryTypes: ['measure', 'resource'] });
// 标记和测量
performance.mark('start');
doSomething();
performance.mark('end');
performance.measure('task', 'start', 'end');
内存监控
JavaScript
// 检测内存使用(Chrome)
if (performance.memory) {
console.log({
used: performance.memory.usedJSHeapSize,
total: performance.memory.totalJSHeapSize,
limit: performance.memory.jsHeapSizeLimit
});
}
长任务检测
JavaScript
const observer = new PerformanceObserver(list => {
list.getEntries().forEach(entry => {
console.log('长任务:', entry.duration + 'ms');
});
});
observer.observe({ entryTypes: ['longtask'] });
注意事项
- 避免在循环中操作DOM,使用DocumentFragment批量处理
- 使用WeakMap/WeakSet存储DOM引用,避免内存泄漏
- 大数据处理考虑Web Workers分担主线程压力
- 定时器和事件监听器必须在不需要时清理
要点总结
- 减少重排重绘,批量操作DOM
- 防抖节流控制高频事件触发频率
- 及时清理定时器、事件监听器避免内存泄漏
- 使用WeakMap存储DOM引用,自动释放内存
- Performance API监控性能指标
存放路径:articles/JS/进阶/浏览器与DOM高级/性能优化与内存管理.md
📝 发现内容有误?点击此处直接编辑