Proxy 是 JavaScript 中唯一能从语言层面拦截对象基本操作的机制,覆盖 13 类核心 trap(如 get、set、has 等),可拦截绝大多数运行时交互,但无法拦截私有字段、原始值、绕过代理的操作及 Object.prototype 内置调用。

Proxy 是 JavaScript 中唯一能从语言层面拦截对象基本操作的机制,它的覆盖范围明确、全面,但也有清晰边界。它不是万能补丁,也不是对所有行为都生效,关键在于“谁在调用”“怎么调用”“调用什么”。
能拦截的 13 类核心操作(trap)
这些是 Proxy handler 中可定义的拦截点,每个对应一项底层语义操作:-
get:读取属性(
obj.x、obj['x'])、访问原型链属性、in操作符判断、for...in枚举中的键访问(配合ownKeys) -
set:赋值操作(
obj.x = v、obj['x'] = v),严格模式下返回false会抛错 -
has:拦截
'x' in obj,控制“是否存在”的逻辑语义 -
deleteProperty:拦截
delete obj.x,可拒绝删除或触发清理 -
ownKeys:拦截
Object.keys()、Object.getOwnPropertyNames()、for...in等枚举行为,可隐藏/动态添加键名 -
getOwnPropertyDescriptor:拦截
Object.getOwnPropertyDescriptor(obj, 'x'),可伪造或过滤描述符 -
defineProperty:拦截
Object.defineProperty(obj, 'x', ...),控制属性是否可被定义 -
apply:仅对函数有效,拦截
fn()调用,用于装饰、参数校验、日志等 -
construct:仅对构造函数有效,拦截
new Fn(),可返回自定义实例 - isExtensible、preventExtensions、getPrototypeOf、setPrototypeOf:控制对象可扩展性与原型链操作
这些 trap 覆盖了对象绝大多数运行时交互场景,且全部通过引擎原生支持,性能优于 Object.defineProperty 的模拟方式。
能间接影响但不直接拦截的行为
有些操作本身不触发 trap,但可通过组合 trap 实现类似效果:-
JSON.stringify():不走任何 trap,但可通过重写
toJSON方法或在get中拦截该属性返回定制值 -
toString() / valueOf():若方法定义在实例自身,
get可拦截;若来自原型,需在get中显式处理(例如检查prop === 'toString'并返回包装函数) -
数组方法如 push、pop:它们本质是函数调用,
apply或get+ 函数包装可拦截;但内部索引更新(如arr[0] = x)仍走set
明确无法拦截的几类情况
这些是 Proxy 的硬性限制,强行尝试会失效或报错:- 私有字段(#field):语法层面直接拒绝访问,不进入任何 trap,也无法代理
-
原始值(string/number/boolean/null/undefined):Proxy 只接受对象,传入原始值会抛
TypeError -
绕过代理的操作:直接修改原始目标对象(
target.x = 1),不会触发 proxy 的set -
非对象属性的嵌套访问:如
proxy.a.b = 1,若a是普通对象而非 Proxy,则对b的赋值不触发set -
Object.prototype 上的内置调用:如
Object.prototype.toString.call(proxy)不触发get,但可用Symbol.toStringTag微调输出
Proxy 的设计哲学是“代理访问”,不是“监控内存”。它只在你通过 Proxy 实例发起操作时生效,不自动递归、不监听引用变化、也不替代底层引擎行为。


















