减少重绘和回流
频繁操作 DOM 会导致浏览器反复计算布局,触发重绘和回流。使用 documentFragment 进行批量 DOM 操作,或通过修改 className 一次性应用样式变更。对复杂动画元素使用 transform 和 opacity 属性,这些属性由合成器线程处理,不会触发主线程布局计算。
// 使用 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);
}
});
内存管理
及时清除不再使用的定时器、事件监听器和对象引用。使用 WeakMap 和 WeakSet 存储临时数据,避免内存泄漏。对于大型数据集,采用惰性加载或分页加载策略。
// 清除无效引用
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);
}
}
JavaScript性能优化技巧
944

被折叠的 条评论
为什么被折叠?



