原型链通过属性查找机制和方法重写实现无侵入监控,常用方式包括重写全局对象原型方法、实例方法遮蔽、proxy拦截及封装基类模板。

原型链本身不直接提供“拦截”能力,但它为方法调用提供了可干预的入口——关键在于利用属性查找机制(就近优先)和原型方法重写,在不侵入业务逻辑的前提下,把监控逻辑“织入”调用链。
用原型方法重写实现无侵入监控
对全局稳定对象(如 XMLHttpRequest.prototype、fetch)的方法进行安全替换,是最常用也最可靠的拦截方式。它启动早、兼容性强,且无需框架支持。
- 先缓存原始方法,例如
const originalSend = XMLHttpRequest.prototype.send - 用
Object.defineProperty或直接赋值重写目标方法,确保writable和configurable允许覆盖(fetch需用defineProperty) - 新方法中调用原始函数时,必须传入正确的
this和参数,推荐统一用originalFn.apply(this, arguments) - 在调用前后插入计时、日志或错误捕获逻辑,比如记录请求 URL、耗时、状态码
用实例方法遮蔽控制调用优先级
原型链的“就近查找”特性天然支持行为覆盖。你不需要修改原型,只需在实例上挂同名方法,就能让后续调用自动走高优逻辑。
- 基础校验放在
Validator.prototype.check,紧急校验直接赋值instance.check = () => { /* 快速路径 */ } - 该方式零运行时开销,切换即时生效,适合 A/B 测试、灰度发布或故障降级
- 注意避免重复定义;可通过
delete instance.method恢复原型链查找
用 Proxy + Reflect 拦截原型访问(进阶可控)
当需要更细粒度控制(比如动态决定从哪个父类取方法),Proxy 可以模拟多源查找,把原型链访问变成可编程过程。
- 在
get(target, prop, receiver)中,依次检查多个原型对象是否含该属性 - 命中后必须用
Reflect.get(obj, prop, receiver)获取,否则 getter 内部this会丢失 - 配合重写
has、getPrototypeOf,才能让in、instanceof等操作也符合预期 - 适用于构建插件化模型、策略组合器或响应式代理,但要注意性能与调试成本
封装成可复用的基类模板
把通用拦截逻辑抽离为基类,子类继承后只需关注业务,监控自动生效。
- 定义
TrackedBase,提供timedCall(methodName, fn)统一封装执行与计时 - 子类方法内部调用
this.timedCall('getData', () => this.fetchData()) - 也可结合装饰器(如
@track)进一步简化,但需构建工具支持











