javascript中proxy拦截函数调用必须使用apply陷阱,而非get;apply在代理函数被直接调用时触发,接收target、thisarg和argumentslist参数,需用reflect.apply执行原函数。

JavaScript 中 Proxy 拦截函数调用,核心靠的是 apply 陷阱(trap)。它只在目标对象是函数、且该代理被当作函数调用时触发,比如 proxy() 或 proxy(1, 2)。这不是拦截“属性访问”,而是直接拦截“执行动作”本身。
必须用 apply,不是 get
很多人误以为给函数对象加 Proxy 后,写个 get 就能拦截调用——其实不行。get 拦截的是“取属性”,比如 proxy.method;而函数真正被调用的那一瞬间,只有 apply 能捕获。
-
apply(target, thisArg, argumentsList)是唯一专为函数调用设计的 trap - 参数含义:target 是原函数,
thisArg是调用时绑定的this,argumentsList是实参数组 - 若想让调用继续执行原函数,需显式调用
target.apply(thisArg, argumentsList)或更推荐的Reflect.apply(target, thisArg, argumentsList)
一个干净的日志拦截示例
下面代码创建一个带日志的函数代理:
Java项目代码review工具。分析Git变更+完整调用链路上下文,推断业务需求,进行多维度评分和分类汇总,生成完整PRD文档。包含细粒度Java代码审查清单(Null安全、异常处理、Streams、并发、equals/hashCode、资源管理、API设计、性能、MyBatis/ORM、事务边界、SQL/DD...
const original = function(x, y) { return x + y; };
const logged = new Proxy(original, {
apply(target, thisArg, args) {
console.log(`[CALL] ${target.name || 'anonymous'}(${args.join(', ')})`);
const result = Reflect.apply(target, thisArg, args);
console.log(`[RETURN] → ${result}`);
return result;
}
});
logged(3, 5); // 输出两行日志,并返回 8
支持 this 绑定和异步函数
apply 会如实接收调用时的 this 和所有参数,因此箭头函数、bind 过的函数、类方法等都能正确处理:
- 如果原函数是
obj.method并被proxy.method()调用,注意:此时proxy.method先走get,再走apply——但这是两个独立代理,需分别处理 - 对 async 函数,
apply返回的仍是 Promise,可直接 await:const res = await Reflect.apply(target, thisArg, args) - 不建议在
apply内部直接写target(...args),因为会丢失this;始终用Reflect.apply或target.call(thisArg, ...args)
和对象方法拦截的区别
如果你想拦截某个对象上“所有方法”的调用(比如 api.get()、api.post()),不能只代理那个对象本身——得在 get 里动态包装每个取出来的函数:
- Proxy 对象本身不自动拦截原型链上的方法调用,但只要方法是从该代理对象上读出的(如
proxy.say),get就能捕获并返回一个带apply的代理函数 - 常见模式:在
get中判断值是否为函数,是则返回一个新的 Proxy 包裹它,这个新 Proxy 的apply做实际拦截逻辑 - 这样既保持原对象结构,又实现“按需增强”,比污染原型更安全、更可控
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










