proxy 不拦截原型操作本身,只拦截对象对原型的访问行为;get/has/ownkeys 等 trap 可控制原型相关行为,set 需注意属性屏蔽机制,receiver 保证正确处理原型 getter/setter,函数访问可借 get 包装实现统一拦截。

Proxy 本身不拦截“原型操作”,只拦截对象对原型的访问行为
JavaScript 中没有“拦截原型操作”这个说法。Proxy 拦截的是对象上的操作行为,比如读属性、写属性、查 in、遍历键等;而原型链只是 JS 属性查找机制的一部分。当你访问 obj.x,引擎会先查 obj 自身,再沿 [[Prototype]] 向上找——这个查找过程本身不可拦截,但每次触发查找的入口操作(如 get、has、ownKeys)可以被 Proxy 拦截。
关键陷阱:get / has / ownKeys 决定你能否感知原型访问
这些 trap 是你控制原型相关行为的主要入口:
-
get(target, prop, receiver):只要代码写了
obj.prop或obj[prop],无论prop在自身还是原型上,都会进这个 trap。你可以用Reflect.get(target, prop, receiver)触发默认查找逻辑,再根据结果做日志、转换或拦截 -
has(target, prop):对应
prop in obj。它同样会触发原型链查找,你可在 trap 中判断是自有还是继承属性,甚至返回 false 来“隐藏”原型上的属性 -
ownKeys(target):只返回目标对象自身的可枚举属性键(不含原型)。若想让
Object.keys(obj)或for...in包含原型属性,需手动合并,但要注意这违背 JS 原生语义,可能引发兼容问题
不能直接修改原型属性?set 的行为要特别注意
当你执行 obj.x = 1 时:
- 如果
x在原型上且是writable: false,JS 不会修改原型,而是在obj上新建自有属性(即屏蔽),此时settrap 仍会被触发,但作用对象是obj自身 - 如果想真正修改原型上的属性,必须确保该属性可写,并把 Proxy 套在原型对象上,而不是实例上
-
receiver参数很重要:它代表原始调用时的 this(通常是 proxy 实例),在get/set中传给Reflect方法,才能正确处理原型链上的 getter/setter
想统一拦截所有实例的原型方法调用?用 Proxy + get 包装函数
这不是拦截“原型操作”,而是拦截“方法访问后调用”的行为:
- 在
gettrap 中检测返回值是否为函数 - 如果是,返回一个新函数,在调用前后插入逻辑(如日志、权限检查)
- 原函数仍通过
Reflect.get获取,调用时用.apply(this, args)保持正确的this和参数 - 这样所有从原型链上获取的方法(如
toString、自定义say)都会被包装,无需改写原型
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











