Object.getPrototypeOf() 本身不提供监控能力,仅用于读取对象原型;但可配合 Proxy、WeakMap 等实现对原型篡改或方法调用的运行时观察,关键在于识别原型结构后在合适位置埋点。

Object.getPrototypeOf() 本身不提供监控能力,它只是读取对象的原型(即 [[Prototype]] 链上的上一级对象)。但你可以把它作为基础工具,配合其他机制(如 Proxy、getter/setter、WeakMap)来实现对实例底层行为的运行时观察。关键不是“用它监控”,而是“用它识别原型结构,再在合适位置埋点”。
明确监控目标:原型链变化 or 原型方法调用?
运行时监控通常关注两类行为:
-
原型被篡改:比如有人执行
Object.setPrototypeOf(obj, newProto)或直接修改obj.__proto__ -
原型上方法被调用:比如每次调用
obj.toString()或自定义的obj.save(),你想记录或拦截
Object.getPrototypeOf() 在这两类场景中分别起不同作用:前者用于检测变更前后的差异;后者用于定位方法定义位置,辅助代理或包装。
监控原型篡改:用 WeakMap 缓存快照 + 定期比对
无法实时拦截 Object.setPrototypeOf(它不可重写),但可以事后发现。思路是为关键实例缓存其初始原型引用,后续按需校验:
const protoCache = new WeakMap();
function watchPrototype(obj) {
if (!protoCache.has(obj)) {
protoCache.set(obj, Object.getPrototypeOf(obj));
}
}
function isPrototypeChanged(obj) {
const cached = protoCache.get(obj);
const current = Object.getPrototypeOf(obj);
return cached !== current;
}
// 使用示例
const user = { name: 'Alice' };
watchPrototype(user);
console.log(isPrototypeChanged(user)); // false
Object.setPrototypeOf(user, Array.prototype);
console.log(isPrototypeChanged(user)); // true
适合低频检查场景(如测试断言、沙箱环境初始化后校验)。注意:=== 比较足够,因为原型对象引用不变即视为未变。
监控原型方法调用:结合 Proxy 和 getPrototypeOf 定位原始方法
若想拦截所有通过原型链触发的方法(包括继承来的),可在实例层用 Proxy 包裹,并利用 Object.getPrototypeOf() 向上查找真实方法定义,避免硬编码:
function createTracingProxy(obj, handler = {}) {
const originalProto = Object.getPrototypeOf(obj);
return new Proxy(obj, {
get(target, prop, receiver) {
const value = Reflect.get(target, prop, receiver);
// 如果是函数,且来自原型(非自身属性),就包装它
if (typeof value === 'function' &&
!target.hasOwnProperty(prop) &&
originalProto[prop] === value) {
return function(...args) {
console.log(`[TRACE] ${prop} called on`, target, 'via', originalProto.constructor?.name);
return value.apply(this, args);
};
}
return value;
}
});
}
// 示例
class Model {
save() { return 'saved'; }
}
const inst = new Model();
const traced = createTracingProxy(inst);
traced.save(); // 输出 TRACE 日志并执行
这种方式不修改原型本身,只在访问时动态增强,适合调试和轻量级运行时分析。
进阶:配合 defineProperty 动态注入 getter/setter 到原型
如果你有权限修改原型(例如控制类定义),可在原型上统一添加受控访问器,再用 Object.getPrototypeOf() 确认是否命中目标原型:
- 在原型上用
Object.defineProperty添加一个通用 getter,内部检查Object.getPrototypeOf(this) === TargetProto - 或使用
Object.getOwnPropertyDescriptors批量包装已有方法 - 注意避免污染原生原型(如
Object.prototype),推荐仅作用于你可控的类原型
这种方案侵入性稍强,但性能更好,适合长期运行的监控模块。










