1. 减少 DOM 操作(重绘与回流)
问题:频繁修改 DOM 触发浏览器重绘(repaint)和回流(reflow),消耗 CPU 资源。
优化方案:
- 使用
DocumentFragment
批量操作 DOM - 通过
classList
替代style
修改样式
// 错误示例:多次触发重排
const list = document.getElementById('list');
for(let i=0; i<1000; i++) {
const item = document.createElement('li');
item.textContent = `Item ${i}`;
list.appendChild(item); // 每次循环触发重排
}
// 优化方案:文档片段批量操作
const fragment = document.createDocumentFragment();
for(let i=0; i<1000; i++) {
const item = document.createElement('li');
item.textContent = `Item ${i}`;
fragment.appendChild(item);
}
list.appendChild(fragment); // 单次重排
2. 事件委托
问题:为大量子元素绑定事件监听器导致内存占用过高。
优化方案:
- 利用事件冒泡,在父级统一处理事件
// 低效写法(每个按钮绑定监听器)
document.querySelectorAll('.btn').forEach(btn => {
btn.addEventListener('click', handleClick);
});
// 优化写法(单事件监听)
document.getElementById('container').addEventListener('click', (e) => {
if (e.target.classList.contains('btn')) {
handleClick(e);
}
});
3. 防抖与节流
问题:高频事件(如 scroll
、resize
)导致函数过度调用。
优化方案:
// 防抖:事件结束后触发
function debounce(fn, delay) {
let timer;
return () => {
clearTimeout(timer);
timer = setTimeout(fn, delay);
};
}
// 节流:固定间隔触发
function throttle(fn, interval) {
let lastTime = 0;
return () => {
const now = Date.now();
if (now - lastTime >= interval) {
fn();
lastTime = now;
}
};
}
// 使用示例
window.addEventListener('resize', debounce(handleResize, 200));
4. Web Workers(多线程计算)
// 主线程
const worker = new Worker('compute.js');
worker.postMessage({ data: largeArray });
worker.onmessage = e => console.log(e.data.result);
// compute.js
self.onmessage = e => {
const result = heavyComputation(e.data.data); // 复杂计算
self.postMessage({ result });
};
5. 内存管理
问题:闭包引用、未解绑事件导致内存泄漏。
优化方案:
- 使用
WeakMap
避免强引用 - 及时移除无用事件监听器
// 典型内存泄漏场景
function init() {
const data = getHugeData();
document.getElementById('btn').addEventListener('click', () => {
// data 被闭包引用,无法释放
processData(data);
});
}
// 优化:解绑事件 + 清除引用
function cleanup() {
btn.removeEventListener('click', processData);
data = null; // 手动释放
}
6. 算法复杂度优化
问题:$$O(n^2)$$ 级算法在大数据量时性能骤降。
优化方案:
- 用
Map
替代Array.indexOf()
($$O(1)$$ vs $$O(n)$$) - 避免嵌套循环,优先使用空间换时间
// 低效:O(n²) 查找重复项
const findDuplicates = (arr) => {
const duplicates = [];
for (let i = 0; i < arr.length; i++) {
for (let j = i + 1; j < arr.length; j++) {
if (arr[i] === arr[j]) duplicates.push(arr[i]);
}
}
return duplicates;
};
// 高效:O(n) 使用 Map
const findDuplicatesOptimized = (arr) => {
const map = new Map();
return arr.filter(item => {
if (map.has(item)) return true;
map.set(item, true);
return false;
});
};
7. 网络请求优化
策略:
- 使用
HTTP/2
多路复用替代并行请求 - 通过
Web Workers
分流计算密集型任务
// 主线程
const worker = new Worker('calc-worker.js');
worker.postMessage({ data: largeArray });
worker.onmessage = (e) => {
console.log('Result:', e.data);
};
// calc-worker.js
self.onmessage = (e) => {
const result = heavyCalculation(e.data);
self.postMessage(result);
};
8.性能检测工具
- Chrome DevTools:
- Performance面板分析运行时性能
- Memory面板追踪内存泄漏
- Lighthouse:自动化性能评分
- Console API:
console.time('render'); renderComponent(); console.timeEnd('render'); // 输出执行时间
关键指标:首次内容渲染(FCP)<1.5s,交互响应时间(TTI)<2s,总阻塞时间(TBT)<200ms
通过以上实战技巧,结合性能监测工具,可显著提升JavaScript应用执行效率。记住:优先解决瓶颈点(遵循$80/20$法则),持续优化才能保持高性能。