javascript中proxy通过apply拦截器拦截函数调用,需显式调用reflect.apply转发;它接收target、thisarg和args,支持参数校验、日志等操作,但不自动执行原函数。

JavaScript 中 Proxy 通过 apply 拦截器来拦截函数调用行为。它不直接代理普通函数(因函数默认不可扩展),而是包装一个可被调用的对象,让每次调用都经过 handler.apply 处理。
核心:用 apply 拦截函数执行
apply 是唯一专门用于拦截函数调用的 trap。当代理对象被当作函数调用时(如 proxy(1, 2) 或 proxy.call(obj, 1, 2)),它就会触发:
- target:原始函数(即被代理的目标)
-
thisArg:调用时绑定的
this值 - args:传入的参数数组(真实、未修改的原始参数)
你可以在里面做校验、过滤、日志、重排、提前返回等操作,再决定是否真正执行原函数。
必须配合 Reflect.apply 才能转发调用
Proxy 不会自动执行原函数;你需要显式调用 Reflect.apply(target, thisArg, args) 来触发默认行为。这是安全且标准的做法:
- 避免手动调用
target(...args),防止丢失this绑定或原型链 -
Reflect.apply保证语义与原生调用一致,包括对箭头函数、构造器等的兼容性 - 若想跳过执行,可直接返回默认值或抛错,无需调用
Reflect.apply
实际例子:参数过滤 + 日志记录
比如封装一个 API 函数,自动剔除 null/undefined 参数,并打印调用信息:
function api(url, method, headers, body) {
console.log('真实执行:', { url, method, headers, body });
}
const safeApi = new Proxy(api, {
apply(target, thisArg, args) {
console.log('拦截调用,原始参数:', args);
const filtered = args.filter(v => v != null);
console.log('过滤后参数:', filtered);
return Reflect.apply(target, thisArg, filtered);
}
});
safeApi("https://a.com", null, { auth: "x" }, undefined, "data");
// 输出:
// 拦截调用,原始参数: ["https://a.com", null, {auth:"x"}, undefined, "data"]
// 过滤后参数: ["https://a.com", {"auth":"x"}, "data"]
// 真实执行: {url: "...", method: undefined, headers: {auth:"x"}, body: "data"}
注意边界情况
不是所有“像函数”的东西都能被 Proxy 正常拦截:
-
箭头函数:无法通过
get拦截(无this和prototype),但只要它是target,apply仍生效 -
bind 后的函数:Proxy 可以代理,但
thisArg可能已被固定,需留意上下文 -
Generator 函数:
apply会触发,但返回的是迭代器;如需拦截迭代过程,得额外处理next等方法 -
构造函数调用:若需拦截
new proxy(...),要用constructtrap,而非apply
不复杂但容易忽略
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











