如何使用JS Proxy测量类中所有函数的执行时间
类方法执行时间测量:修复Proxy问题及RxJS实现方案
修复Proxy的this指向问题
你用return () => target[prop]();导致原方法执行异常,核心原因是箭头函数丢失了正确的this指向。箭头函数没有自己的this,调用时会继承get拦截器的上下文,而不是Foo类的实例,这会导致原方法的this绑定错误,甚至无法正确执行。
正确的做法是返回一个普通包装函数,在函数内部用Reflect.apply确保原方法的this指向Proxy实例(也就是Foo的实例),同时记录执行时间:
class Foo { constructor() { return new Proxy(this, { get(target, prop, receiver) { const originalMethod = target[prop]; // 仅拦截函数类型的属性 if (typeof originalMethod === 'function') { return function(...args) { const startTime = performance.now(); // 用Reflect.apply保证this指向正确,同时传递所有参数 const result = Reflect.apply(originalMethod, this, args); const endTime = performance.now(); console.log(`方法 '${prop}' 执行耗时:${endTime - startTime}ms`); return result; }; } // 非函数属性直接返回原值 return originalMethod; }, }); } myFn() { console.log('hi'); } heavyTask() { let total = 0; for (let i = 0; i < 1e6; i++) total += i; return total; } } const foo = new Foo(); foo.myFn(); // 输出: hi + 耗时日志 foo.heavyTask(); // 输出求和结果 + 耗时日志
用RxJS实现的方案
如果你的项目已经在使用RxJS,可以把方法执行包装成Observable流,在流中完成时间测量。这种方式适合需要结合RxJS其他操作(如异步处理、重试、节流)的场景:
import { Observable } from 'rxjs'; class Foo { constructor() { return new Proxy(this, { get(target, prop, receiver) { const originalMethod = target[prop]; if (typeof originalMethod === 'function') { return function(...args) { return new Observable(subscriber => { const startTime = performance.now(); try { const result = Reflect.apply(originalMethod, this, args); subscriber.next(result); subscriber.complete(); const endTime = performance.now(); console.log(`方法 '${prop}' 执行耗时:${endTime - startTime}ms`); } catch (err) { subscriber.error(err); } }); }; } return originalMethod; }, }); } myFn() { console.log('hi'); return '执行完成'; } asyncTask() { return new Promise(resolve => setTimeout(() => resolve('异步任务完成'), 1000)); } } const foo = new Foo(); // 同步方法订阅 foo.myFn().subscribe(res => console.log('结果:', res)); // 异步方法订阅 foo.asyncTask().subscribe(res => console.log('异步结果:', res));
如果只是单纯测量执行时间,纯Proxy方案更轻量;如果需要处理异步逻辑或结合RxJS生态,上述RxJS方案更合适。
内容的提问来源于stack exchange,提问作者teteyi3241
相关产品推荐
相关产品推荐

