JavaScript系列(25)--性能优化技术详解
JavaScript性能优化技术详解 ⚡
今天,让我们深入探讨JavaScript的性能优化技术。掌握这些技术对于构建高性能的JavaScript应用至关重要。
性能优化基础 🌟
💡 小知识:JavaScript性能优化涉及多个方面,包括代码执行效率、内存使用、网络请求、渲染性能等。通过合理的优化策略,我们可以显著提升应用的响应速度和用户体验。
代码执行优化 📊
// 1. 循环优化
function loopOptimization() {
const arr = new Array(1000000).fill(1);
// 不好的做法
for (let i = 0; i < arr.length; i++) {
// 每次都要获取数组长度
}
// 好的做法
for (let i = 0, len = arr.length; i < len; i++) {
// 缓存数组长度
}
// 更好的做法
arr.forEach(item => {
// 使用原生方法
});
// 最好的做法(特定场景)
const typedArr = new Float64Array(1000000);
// 使用类型化数组提升性能
}
// 2. 函数优化
class FunctionOptimizer {
// 函数记忆化
static memoize(fn) {
const cache = new Map();
return (...args) => {
const key = JSON.stringify(args);
if (cache.has(key)) {
return cache.get(key);
}
const result = fn.apply(this, args);
cache.set(key, result);
return result;
};
}
// 函数去抖
static debounce(fn, delay) {
let timeoutId;
return function(...args) {
clearTimeout(timeoutId);
timeoutId = setTimeout(() => fn.apply(this, args), delay);
};
}
// 函数节流
static throttle(fn, limit) {
let inThrottle;
return function(...args) {
if (!inThrottle) {
fn.apply(this, args);
inThrottle = true;
setTimeout(() => inThrottle = false, limit);
}
};
}
}
// 3. 数据结构优化
class DataStructureOptimizer {
// Map vs Object性能比较
static mapVsObject() {
const map = new Map();
const obj = {};
const iterations = 1000000;
console.time('Map');
for (let i = 0; i < iterations; i++) {
map.set(i, i);
map.get(i);
}
console.timeEnd('Map');
console.time('Object');
for (let i = 0; i < iterations; i++) {
obj[i] = i;
obj[i];
}
console.timeEnd('Object');
}
// Set vs Array性能比较
static setVsArray() {
const set = new Set();
const arr = [];
const iterations = 1000000;
console.time('Set');
for (let i = 0; i < iterations; i++) {
set.add(i);
set.has(i);
}
console.timeEnd('Set');
console.time('Array');
for (let i = 0; i < iterations; i++) {
arr.push(i);
arr.includes(i);
}
console.timeEnd('Array');
}
}
内存优化技术 🚀
// 1. 对象池实现
class ObjectPool {
constructor(factory, initialSize = 10) {
this.factory = factory;
this.pool = [];
this.init(initialSize);
}
init(size) {
for (let i = 0; i < size; i++) {
this.pool.push(this.factory());
}
}
acquire() {
return this.pool.length > 0
? this.pool.pop()
: this.factory();
}
release(obj) {
if (this.pool.length < this.maxSize) {
if (obj.reset) obj.reset();
this.pool.push(obj);
}
}
}
// 2. 内存泄漏防护
class MemoryLeakGuard {
constructor() {
this.observers = new WeakSet();
this.eventHandlers = new WeakMap();
}
observe(target) {
if (!this.observers.has(target)) {
this.observers.add(target);
this.eventHandlers.set(target, new Map());
}
}
addHandler(target, event, handler) {
if (this.eventHandlers.has(target)) {
const handlers = this.eventHandlers.get(target);
handlers.set(event, handler);
target.addEventListener(event, handler);
}
}
removeHandler(target, event) {
if (this.eventHandlers.has(target)) {
const handlers = this.eventHandlers.get(target);
const handler = handlers.get(event);
if (handler) {
target.removeEventListener(event, handler);
handlers.delete(event);
}
}
}
cleanup(target) {
if (this.eventHandlers.has(target)) {
const handlers = this.eventHandlers.get(target);
handlers.forEach((handler, event) => {
target.removeEventListener(event, handler);
});
this.eventHandlers.delete(target);
this.observers.delete(target);
}
}
}
// 3. 大数据处理优化
class BigDataProcessor {
// 分片处理
static async processInChunks(items, chunkSize, processor) {
const results = [];
for (let i = 0; i < items.length; i += chunkSize) {
const chunk = items.slice(i, i + chunkSize);
const chunkResults = await Promise.all(
chunk.map(item => processor(item))
);
results.push(...chunkResults);
// 让出主线程
await new Promise(resolve => setTimeout(resolve, 0));
}
return results;
}
// 虚拟列表实现
static createVirtualList(container, items, rowHeight) {
let scrollTop = 0;
let visibleItems = [];
function updateVisibleItems() {
const containerHeight = container.clientHeight;
const startIndex = Math.floor(scrollTop / rowHeight);
const endIndex = Math.min(
startIndex + Math.ceil(containerHeight / rowHeight),
items.length
);
visibleItems = items.slice(startIndex, endIndex).map((item, index) => ({
...item,
style: {
position: 'absolute',
top: (startIndex + index) * rowHeight + 'px',
height: rowHeight + 'px'
}
}));
render();
}
function render() {
container.innerHTML = '';
visibleItems.forEach(item => {
const element = document.createElement('div');
Object.assign(element.style, item.style);
element.textContent = item.content;
container.appendChild(element);
});
}
container.style.height = items.length * rowHeight + 'px';
container.style.position = 'relative';
container.style.overflow = 'auto';
container.addEventListener('scroll', () => {
scrollTop = container.scrollTop;
updateVisibleItems();
});
updateVisibleItems();
}
}
网络优化策略 🌐
// 1. 请求优化
class RequestOptimizer {
constructor() {
this.cache = new Map();
this.pendingRequests = new Map();
}
// 请求去重
async request(url, options = {}) {
const key = `${url}-${JSON.stringify(options)}`;
// 检查缓存
if (this.cache.has(key)) {
return this.cache.get(key);
}
// 检查是否有相同的请求正在进行
if (this.pendingRequests.has(key)) {
return this.pendingRequests.get(key);
}
// 发起新请求
const promise = fetch(url, options)
.then(response => response.json())
.finally(() => {
this.pendingRequests.delete(key);
});
this.pendingRequests.set(key, promise);
const result = await promise;
this.cache.set(key, result);
return result;
}
// 批量请求
async batchRequest(urls, options = {}) {
return Promise.all(
urls.map(url => this.request(url, options))
);
}
}
// 2. 资源预加载
class ResourcePreloader {
constructor() {
this.loaded = new Set();
}
preloadImage(url) {
if (this.loaded.has(url)) return Promise.resolve();
return new Promise((resolve, reject) => {
const img = new Image();
img.onload = () => {
this.loaded.add(url);
resolve();
};
img.onerror = reject;
img.src = url;
});
}
preloadScript(url) {
if (this.loaded.has(url)) return Promise.resolve();
return new Promise((resolve, reject) => {
const script = document.createElement('script');
script.onload = () => {
this.loaded.add(url);
resolve();
};
script.onerror = reject;
script.src = url;
document.head.appendChild(script);
});
}
preloadStyle(url) {
if (this.loaded.has(url)) return Promise.resolve();
return new Promise((resolve, reject) => {
const link = document.createElement('link');
link.rel = 'stylesheet';
link.onload = () => {
this.loaded.add(url);
resolve();
};
link.onerror = reject;
link.href = url;
document.head.appendChild(link);
});
}
}
// 3. 数据缓存策略
class CacheStrategy {
constructor(storage = localStorage) {
this.storage = storage;
this.prefix = 'cache_';
}
set(key, value, ttl = 3600000) { // 默认1小时
const item = {
value,
timestamp: Date.now(),
ttl
};
this.storage.setItem(
this.prefix + key,
JSON.stringify(item)
);
}
get(key) {
const item = JSON.parse(
this.storage.getItem(this.prefix + key)
);
if (!item) return null;
if (Date.now() - item.timestamp > item.ttl) {
this.storage.removeItem(this.prefix + key);
return null;
}
return item.value;
}
clear() {
Object.keys(this.storage)
.filter(key => key.startsWith(this.prefix))
.forEach(key => this.storage.removeItem(key));
}
}
渲染性能优化 🎨
// 1. DOM操作优化
class DOMOptimizer {
// 批量DOM更新
static batchUpdate(elements, updates) {
const fragment = document.createDocumentFragment();
elements.forEach(element => {
const clone = element.cloneNode(true);
updates(clone);
fragment.appendChild(clone);
});
elements[0].parentNode.replaceChildren(fragment);
}
// 虚拟DOM实现
static createVirtualDOM(element) {
return {
type: element.tagName.toLowerCase(),
props: Array.from(element.attributes).reduce((props, attr) => {
props[attr.name] = attr.value;
return props;
}, {}),
children: Array.from(element.childNodes).map(node => {
if (node.nodeType === 3) return node.textContent;
return this.createVirtualDOM(node);
})
};
}
// 最小化重排重绘
static optimizeReflow(element, updates) {
const originalDisplay = element.style.display;
element.style.display = 'none';
updates(element);
element.style.display = originalDisplay;
}
}
// 2. 动画性能优化
class AnimationOptimizer {
constructor() {
this.animations = new Map();
}
// 使用requestAnimationFrame
animate(element, properties, duration) {
const startTime = performance.now();
const initialValues = {};
Object.keys(properties).forEach(prop => {
initialValues[prop] = parseFloat(
getComputedStyle(element)[prop]
);
});
const animation = timestamp => {
const progress = (timestamp - startTime) / duration;
if (progress < 1) {
Object.keys(properties).forEach(prop => {
const initial = initialValues[prop];
const target = properties[prop];
const current = initial + (target - initial) * progress;
element.style[prop] = current + 'px';
});
this.animations.set(
element,
requestAnimationFrame(animation)
);
} else {
Object.keys(properties).forEach(prop => {
element.style[prop] = properties[prop] + 'px';
});
this.animations.delete(element);
}
};
this.animations.set(
element,
requestAnimationFrame(animation)
);
}
// 停止动画
stop(element) {
if (this.animations.has(element)) {
cancelAnimationFrame(this.animations.get(element));
this.animations.delete(element);
}
}
}
// 3. 图片优化
class ImageOptimizer {
// 图片懒加载
static lazyLoad(images) {
const observer = new IntersectionObserver(
(entries, observer) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
const img = entry.target;
img.src = img.dataset.src;
observer.unobserve(img);
}
});
}
);
images.forEach(img => observer.observe(img));
}
// 图片预加载
static preload(urls) {
return Promise.all(
urls.map(url => {
return new Promise((resolve, reject) => {
const img = new Image();
img.onload = resolve;
img.onerror = reject;
img.src = url;
});
})
);
}
// 响应式图片
static createResponsiveImage(url, sizes) {
const img = document.createElement('img');
img.srcset = sizes.map(size =>
`${url}-${size}w.jpg ${size}w`
).join(', ');
img.sizes = '(max-width: 768px) 100vw, 50vw';
return img;
}
}
最佳实践建议 💡
- 性能监控
// 1. 性能监控工具
class PerformanceMonitor {
constructor() {
this.metrics = new Map();
}
// 测量执行时间
measure(name, fn) {
const start = performance.now();
const result = fn();
const duration = performance.now() - start;
this.metrics.set(name, {
duration,
timestamp: Date.now()
});
return result;
}
// 异步操作测量
async measureAsync(name, fn) {
const start = performance.now();
const result = await fn();
const duration = performance.now() - start;
this.metrics.set(name, {
duration,
timestamp: Date.now()
});
return result;
}
// 获取性能报告
getReport() {
return Array.from(this.metrics.entries())
.map(([name, data]) => ({
name,
duration: data.duration,
timestamp: new Date(data.timestamp).toISOString()
}));
}
}
// 2. 性能优化检查清单
class PerformanceChecker {
static checkDOMSize() {
return document.querySelectorAll('*').length;
}
static checkEventListeners() {
const elements = document.querySelectorAll('*');
let count = 0;
elements.forEach(element => {
const listeners = getEventListeners(element);
count += Object.keys(listeners).reduce(
(sum, type) => sum + listeners[type].length,
0
);
});
return count;
}
static checkMemoryUsage() {
if (performance.memory) {
return {
usedJSHeapSize: performance.memory.usedJSHeapSize,
totalJSHeapSize: performance.memory.totalJSHeapSize
};
}
return null;
}
}
结语 📝
JavaScript性能优化是一个持续的过程,需要我们在开发过程中不断关注和改进。我们学习了:
- 代码执行优化技术
- 内存使用优化策略
- 网络请求优化方法
- 渲染性能优化技巧
- 性能监控和最佳实践
💡 学习建议:性能优化应该是渐进式的,先找出性能瓶颈,然后针对性地进行优化。使用性能监控工具来量化优化效果,避免过早优化。
如果你觉得这篇文章有帮助,欢迎点赞收藏,也期待在评论区看到你的想法和建议!👇
终身学习,共同成长。
咱们下一期见
💻