前言
javascript在浏览器中运行的性能,可以认为是开发者所面临的最严重的可用性问题。为了帮助大家有效的解决这个问题,今天给大家分享下这篇文章。
这个问题因为javascript的阻塞性而变得复杂,事实上,多数浏览器使用单一进程来处理用户界面和js脚本执行,所以同一时刻只能做一件事。js执行过程耗时越久,浏览器等待响应的时间越长 。
小知识:javascript性能优化涉及多个方面,包括代码执行效率、内存使用、dom操作、网络请求等。通过合理的优化策略,可以显著提升应用的响应速度和用户体验。
性能分析工具实现
// 1. 性能计时器
class performancetimer {
constructor() {
this.marks = new map();
this.measures = new map();
}
mark(name) {
this.marks.set(name, performance.now());
}
measure(name, startmark, endmark) {
const starttime = this.marks.get(startmark);
const endtime = this.marks.get(endmark);
if (starttime && endtime) {
const duration = endtime - starttime;
this.measures.set(name, duration);
return duration;
}
return null;
}
getmeasure(name) {
return this.measures.get(name);
}
clearmarks() {
this.marks.clear();
}
clearmeasures() {
this.measures.clear();
}
}
// 2. 代码性能分析器
class codeprofiler {
constructor() {
this.profiles = new map();
}
startprofile(name) {
const starttime = performance.now();
const startmemory = performance.memory?.usedjsheapsize;
this.profiles.set(name, {
starttime,
startmemory,
calls: 0,
totaltime: 0,
maxtime: 0
});
}
endprofile(name) {
const profile = this.profiles.get(name);
if (!profile) return;
const endtime = performance.now();
const endmemory = performance.memory?.usedjsheapsize;
const duration = endtime - profile.starttime;
const memorydiff = endmemory - profile.startmemory;
profile.calls++;
profile.totaltime += duration;
profile.maxtime = math.max(profile.maxtime, duration);
profile.lastmemoryimpact = memorydiff;
}
getprofile(name) {
const profile = this.profiles.get(name);
if (!profile) return null;
return {
...profile,
averagetime: profile.totaltime / profile.calls
};
}
getallprofiles() {
const results = {};
for (const [name, profile] of this.profiles) {
results[name] = this.getprofile(name);
}
return results;
}
}
// 3. 函数执行时间分析装饰器
function profileexecution(target, propertykey, descriptor) {
const originalmethod = descriptor.value;
const profiler = new codeprofiler();
descriptor.value = function(...args) {
profiler.startprofile(propertykey);
const result = originalmethod.apply(this, args);
profiler.endprofile(propertykey);
console.log(`function ${propertykey} profile:`, profiler.getprofile(propertykey));
return result;
};
return descriptor;
}代码优化技术
// 1. 循环优化
class loopoptimizer {
// 优化数组遍历
static optimizedforeach(array, callback) {
const length = array.length;
for (let i = 0; i < length; i++) {
callback(array[i], i);
}
}
// 分块处理大数组
static *chunkedprocess(array, chunksize = 1000) {
const length = array.length;
for (let i = 0; i < length; i += chunksize) {
yield array.slice(i, math.min(i + chunksize, length));
}
}
// 使用web worker处理耗时操作
static createworkerprocess(workerfunction) {
const blob = new blob([`(${workerfunction.tostring()})()`],
{ type: 'application/javascript' });
return new worker(url.createobjecturl(blob));
}
}
// 2. 函数优化
class functionoptimizer {
constructor() {
this.cache = new map();
}
// 函数记忆化
memoize(fn) {
return (...args) => {
const key = json.stringify(args);
if (this.cache.has(key)) {
return this.cache.get(key);
}
const result = fn.apply(this, args);
this.cache.set(key, result);
return result;
};
}
// 函数防抖
debounce(fn, delay) {
let timeoutid;
return (...args) => {
cleartimeout(timeoutid);
timeoutid = settimeout(() => fn.apply(this, args), delay);
};
}
// 函数节流
throttle(fn, limit) {
let inthrottle;
return (...args) => {
if (!inthrottle) {
fn.apply(this, args);
inthrottle = true;
settimeout(() => inthrottle = false, limit);
}
};
}
}
// 3. dom优化
class domoptimizer {
constructor() {
this.mutationobserver = null;
this.virtualdom = new map();
}
// 批量dom更新
batchupdate(updates) {
const fragment = document.createdocumentfragment();
updates.foreach(update => {
const element = this.createelement(update);
fragment.appendchild(element);
});
document.body.appendchild(fragment);
}
// 虚拟dom实现
createelement(vnode) {
if (typeof vnode === 'string') {
return document.createtextnode(vnode);
}
const element = document.createelement(vnode.tag);
for (const [key, value] of object.entries(vnode.props || {})) {
element.setattribute(key, value);
}
(vnode.children || []).foreach(child => {
element.appendchild(this.createelement(child));
});
return element;
}
// dom变更监控
observechanges(target, callback) {
this.mutationobserver = new mutationobserver(callback);
this.mutationobserver.observe(target, {
childlist: true,
subtree: true,
attributes: true
});
}
}高级优化模式
// 1. 虚拟滚动实现
class virtualscroller {
constructor(container, items, itemheight) {
this.container = container;
this.items = items;
this.itemheight = itemheight;
this.visibleitems = new map();
this.scrolltop = 0;
this.container.style.overflow = 'auto';
this.container.style.position = 'relative';
this.init();
}
init() {
// 设置容器高度
this.container.style.height = `${this.items.length * this.itemheight}px`;
// 监听滚动事件
this.container.addeventlistener('scroll', this.onscroll.bind(this));
// 初始渲染
this.render();
}
onscroll() {
this.scrolltop = this.container.scrolltop;
this.render();
}
render() {
const startindex = math.floor(this.scrolltop / this.itemheight);
const endindex = math.min(
startindex + math.ceil(this.container.clientheight / this.itemheight),
this.items.length
);
// 移除不可见项
for (const [index, element] of this.visibleitems) {
if (index < startindex || index >= endindex) {
element.remove();
this.visibleitems.delete(index);
}
}
// 添加可见项
for (let i = startindex; i < endindex; i++) {
if (!this.visibleitems.has(i)) {
const element = this.createitem(i);
this.container.appendchild(element);
this.visibleitems.set(i, element);
}
}
}
createitem(index) {
const element = document.createelement('div');
element.style.position = 'absolute';
element.style.top = `${index * this.itemheight}px`;
element.style.height = `${this.itemheight}px`;
element.textcontent = this.items[index];
return element;
}
}
// 2. 资源预加载器
class resourcepreloader {
constructor() {
this.cache = new map();
this.loading = new set();
}
preload(resources) {
resources.foreach(resource => {
if (!this.cache.has(resource) && !this.loading.has(resource)) {
this.loading.add(resource);
const promise = this.loadresource(resource)
.then(result => {
this.cache.set(resource, result);
this.loading.delete(resource);
})
.catch(error => {
console.error(`failed to preload ${resource}:`, error);
this.loading.delete(resource);
});
return promise;
}
});
}
loadresource(resource) {
if (resource.endswith('.js')) {
return this.loadscript(resource);
} else if (resource.endswith('.css')) {
return this.loadstyle(resource);
} else if (/\.(png|jpg|gif|svg)$/.test(resource)) {
return this.loadimage(resource);
}
return promise.reject(new error('unsupported resource type'));
}
loadscript(url) {
return new promise((resolve, reject) => {
const script = document.createelement('script');
script.src = url;
script.onload = () => resolve(script);
script.onerror = reject;
document.head.appendchild(script);
});
}
loadstyle(url) {
return new promise((resolve, reject) => {
const link = document.createelement('link');
link.rel = 'stylesheet';
link.href = url;
link.onload = () => resolve(link);
link.onerror = reject;
document.head.appendchild(link);
});
}
loadimage(url) {
return new promise((resolve, reject) => {
const img = new image();
img.src = url;
img.onload = () => resolve(img);
img.onerror = reject;
});
}
}
// 3. web worker任务管理器
class workertaskmanager {
constructor(workerscript) {
this.worker = new worker(workerscript);
this.taskqueue = new map();
this.taskid = 0;
this.worker.onmessage = this.handlemessage.bind(this);
this.worker.onerror = this.handleerror.bind(this);
}
executetask(task, data) {
return new promise((resolve, reject) => {
const id = this.taskid++;
this.taskqueue.set(id, { resolve, reject });
this.worker.postmessage({
id,
task,
data
});
});
}
handlemessage(event) {
const { id, result, error } = event.data;
const task = this.taskqueue.get(id);
if (task) {
if (error) {
task.reject(error);
} else {
task.resolve(result);
}
this.taskqueue.delete(id);
}
}
handleerror(error) {
console.error('worker error:', error);
}
terminate() {
this.worker.terminate();
this.taskqueue.clear();
}
}最佳实践建议
性能监控模式
// 1. 性能监控器
class performancemonitor {
constructor() {
this.metrics = new map();
this.thresholds = new map();
}
setthreshold(metric, value) {
this.thresholds.set(metric, value);
}
recordmetric(metric, value) {
if (!this.metrics.has(metric)) {
this.metrics.set(metric, []);
}
const values = this.metrics.get(metric);
values.push({
value,
timestamp: date.now()
});
// 保持最近100个记录
if (values.length > 100) {
values.shift();
}
// 检查是否超过阈值
const threshold = this.thresholds.get(metric);
if (threshold && value > threshold) {
this.handlethresholdexceeded(metric, value, threshold);
}
}
getmetricstats(metric) {
const values = this.metrics.get(metric);
if (!values || values.length === 0) {
return null;
}
const numbers = values.map(v => v.value);
return {
average: numbers.reduce((a, b) => a + b) / numbers.length,
max: math.max(...numbers),
min: math.min(...numbers),
current: numbers[numbers.length - 1]
};
}
handlethresholdexceeded(metric, value, threshold) {
console.warn(`performance threshold exceeded for ${metric}:`, {
value,
threshold,
stats: this.getmetricstats(metric)
});
}
}
// 2. 性能优化建议生成器
class performanceadvisor {
constructor() {
this.rules = new map();
this.initializerules();
}
initializerules() {
this.addrule('longtask', metrics => {
if (metrics.taskduration > 50) {
return {
severity: 'warning',
message: '检测到长任务,考虑使用web worker或任务分割'
};
}
});
this.addrule('memoryleak', metrics => {
if (metrics.memorygrowth > 10000000) { // 10mb
return {
severity: 'error',
message: '检测到可能的内存泄漏'
};
}
});
this.addrule('domsize', metrics => {
if (metrics.domnodes > 1000) {
return {
severity: 'warning',
message: 'dom节点数量过多,考虑使用虚拟滚动或延迟加载'
};
}
});
}
addrule(name, checkfn) {
this.rules.set(name, checkfn);
}
analyze(metrics) {
const issues = [];
for (const [name, checkfn] of this.rules) {
const result = checkfn(metrics);
if (result) {
issues.push({
rule: name,
...result
});
}
}
return issues;
}
}
// 3. 性能报告生成器
class performancereporter {
constructor() {
this.monitor = new performancemonitor();
this.advisor = new performanceadvisor();
}
generatereport() {
const metrics = {
taskduration: this.monitor.getmetricstats('taskduration'),
memorygrowth: this.monitor.getmetricstats('memorygrowth'),
domnodes: this.monitor.getmetricstats('domnodes'),
fps: this.monitor.getmetricstats('fps')
};
const issues = this.advisor.analyze(metrics);
return {
timestamp: date.now(),
metrics,
issues,
recommendations: this.generaterecommendations(issues)
};
}
generaterecommendations(issues) {
const recommendations = new set();
issues.foreach(issue => {
switch (issue.rule) {
case 'longtask':
recommendations.add('考虑使用web worker处理耗时任务');
recommendations.add('实现任务分割和调度');
break;
case 'memoryleak':
recommendations.add('检查闭包和事件监听器');
recommendations.add('使用weakmap/weakset存储对象引用');
break;
case 'domsize':
recommendations.add('实现虚拟滚动');
recommendations.add('使用文档片段批量更新dom');
break;
}
});
return array.from(recommendations);
}
}结语
javascript性能优化是一个持续的过程,需要从多个维度进行考虑和实践。通过本文,我们学习了:
- 性能分析工具的实现
- 代码优化技术
- 高级优化模式
- 性能监控和优化建议
- 最佳实践和设计模式
学习建议:在实际开发中,要根据具体场景选择合适的优化策略。性能优化不是一蹴而就的,需要持续监控和改进。同时,过度优化可能会带来代码可维护性的问题,要在性能和可维护性之间找到平衡。
以上就是javascript性能优化技术深入研究的详细内容,更多关于javascript性能优化的资料请关注代码网其它相关文章!
发表评论