proxy 通过 handler.apply 拦截器间接过滤函数参数,校验、剔除、重排或终止调用;虽不改变原函数签名,但需配合注释或类型定义明确规则。

Proxy 本身不直接“过滤函数参数”,而是通过拦截函数调用行为,间接实现对参数的检查、转换、筛选或拒绝——本质是控制函数执行前的输入流,而非修改参数定义本身。
核心机制:用 Proxy 拦截函数调用
JavaScript 的 Proxy 不能代理普通函数(函数是不可扩展的),但可以代理一个包装后的可调用对象(如带 apply 拦截器的对象),从而在调用时介入参数处理。
关键在于使用 handler.apply 拦截器:它会在目标函数被调用时触发,接收 thisArg、args(原始参数数组)和目标函数本身,允许你:
- 校验参数类型/数量/取值范围
- 剔除无效、重复或敏感参数(即“过滤”)
- 重排、补全、映射参数(如把命名对象转为位置参数)
- 提前终止调用(抛错或返回默认值)
典型场景:自动剔除 undefined 或 null 参数
比如一个 API 方法只接受有效值,你希望调用时自动跳过空值参数:
function apiCall(url, method, headers, body) {
console.log({ url, method, headers, body });
}
const safeApiCall = new Proxy(apiCall, {
apply(target, thisArg, args) {
// 过滤掉 undefined 和 null,保留其他值
const filteredArgs = args.filter(arg => arg !== undefined && arg !== null);
return Reflect.apply(target, thisArg, filteredArgs);
}
});
safeApiCall("https://a.com", null, { auth: "x" }, undefined, "data");
// 实际执行:apiCall("https://a.com", { auth: "x" }, "data")
进阶用法:按规则选择性传递参数
结合参数语义做结构化过滤——例如只传 methodA 关心的第 2 个参数(opt2),忽略其余:
- 定义参数白名单映射:
{ methodA: [1], methodB: [2] }(索引从 0 开始) - 在
apply中根据函数名或上下文提取对应参数子集 - 避免每个方法重复声明长参数列表,统一由 Proxy 调度
这种方式把“参数契约”从函数签名移到拦截逻辑中,提升复用性与维护性。
注意边界:Proxy 不改变原函数签名
被代理函数的 length 属性、toString() 输出仍反映原始定义;IDE 和 TypeScript 也无法自动推导 Proxy 后的行为。因此,生产环境建议配合 JSDoc 注释或类型定义明确说明过滤规则,避免调用方误解。











