getprototypeof 拦截 object.getprototypeof、reflect.getprototypeof、instanceof、isprototypeof 和 proto 访问,但后者已弃用;返回值须为对象或 null,且受目标可扩展性与原型写权限制;in、for...in、hasownproperty 不触发该 trap。

识别 Proxy 拦截 Object.prototype 方法的边界情况,关键在于理解哪些操作**实际触发原型链访问**、哪些只是**语法糖或已弃用特性**,以及 Proxy 的拦截规则对目标对象状态(如可扩展性、属性配置)的强约束。
哪些 Object.prototype 方法会被 getPrototypeOf 拦截
getPrototypeOf trap 会响应以下五种操作,但它们的触发条件和兼容性差异明显:
-
Object.getPrototypeOf(obj):标准、稳定、推荐使用;Proxy 必然拦截 -
Reflect.getPrototypeOf(obj):与上者行为一致,同样被拦截 -
obj instanceof Constructor:本质是检查Constructor.prototype是否在obj的原型链中,因此会多次调用getPrototypeOf向上遍历 -
obj.isPrototypeOf(target):检查obj是否为target的原型,也会触发getPrototypeOf遍历target的整条原型链 -
obj.__proto__:已从 Web 标准中移除,部分浏览器仍支持但不保证被 Proxy 拦截;不应依赖,也不应出现在生产代码中
不可忽略的返回值限制
getPrototypeOf 的返回值不是任意的,违反规则会直接抛出 TypeError:
- 必须返回对象或
null;返回原始值(如42、"foo"、undefined)会报错 - 若目标对象不可扩展(
Object.preventExtensions(target) === true),则必须返回目标对象当前的原型(即Object.getPrototypeOf(target)),不能伪造或替换 - 若目标对象的原型本身被设为不可写(
Object.getOwnPropertyDescriptor(target, '__proto__')显示writable: false),也需确保返回值与其一致
常见误判边界:in、for...in、hasOwnProperty 不走 getPrototypeOf
开发者常误以为这些原型相关操作也会触发 getPrototypeOf,其实它们走的是其他 trap:
-
"prop" in obj→ 触发hastrap,不是getPrototypeOf -
for (let k in obj) { }→ 触发ownKeys+getPrototypeOf协同工作,但仅当遍历需要向上查找继承属性时才调用getPrototypeOf;若ownKeys返回完整键集且无继承属性,getPrototypeOf可能完全不执行 -
obj.hasOwnProperty("prop")→ 只查自身属性,不访问原型链,不触发任何原型相关 trap
instanceof 的隐式多层调用容易被忽略
a instanceof B 的过程是:
→ 获取 B.prototype
→ 对 a 反复调用 getPrototypeOf(a),直到返回值等于 B.prototype 或 null
这意味着:
- 若代理对象的原型链很深,
getPrototypeOf会被连续调用多次 - 若某次返回值不是对象或
null(比如忘了 return),第一次遍历时就报错,后续无法继续 - 若在
getPrototypeOf中做了副作用操作(如计数、日志),要注意它可能被高频、重复触发











