Proxy 的 apply 拦截器可用于函数调用前的参数类型校验,需将目标设为函数,通过遍历 args 与 types 数组比对 typeof 或使用 instanceof 等精确判断,校验失败则抛出错误阻止执行。

可以在函数对象上创建 Proxy,通过 apply 拦截器捕获调用过程,在执行前校验参数类型。
用 Proxy 的 apply 拦截器拦截函数调用
Proxy 的 apply 拦截器专门用于拦截对函数的调用(即 fn(...args)),它接收目标函数、this 上下文和实参数组,适合做前置校验。
- 必须将被代理对象设为函数(不能是普通对象)
-
apply中可访问所有传入参数,便于逐个检查类型 - 校验失败时可抛出错误,阻止原函数执行
定义类型检查规则并封装校验逻辑
建议把类型声明写成数组,每个元素对应一个参数的期望类型(如 ['number', 'string']),再在 apply 中比对 typeof 或使用更精确判断(如 Array.isArray、instanceof)。
- 基础类型用
typeof arg === 'xxx'(注意null返回'object') - 引用类型可用
arg instanceof XXX或Object.prototype.toString.call(arg) - 支持可选参数或联合类型需额外逻辑,例如允许
string | undefined
实际示例:带类型约束的加法函数
下面是一个只接受两个数字参数的 add 函数代理:
立即学习“Java免费学习笔记(深入)”;
const add = (a, b) => a + b;<br>const addSafe = new Proxy(add, {<br> apply(target, thisArg, args) {<br> if (args.length !== 2) throw new TypeError('Expected 2 arguments');<br> if (typeof args[0] !== 'number' || typeof args[1] !== 'number') {<br> throw new TypeError('Both arguments must be numbers');<br> }<br> return Reflect.apply(target, thisArg, args);<br> }<br>});<br><br>// 正确<br>addSafe(2, 3); // → 5<br>// 报错<br>addSafe('2', 3); // → TypeError
扩展思路:支持类型注解风格的声明
可以封装一个辅助函数,让开发者用类似 TypeScript 的方式声明参数类型:
function typed(fn, types) {<br> return new Proxy(fn, {<br> apply(target, thisArg, args) {<br> for (let i = 0; i < args.length; i++) {<br> const expected = types[i];<br> const actual = args[i];<br> if (!expected) continue; // 忽略未声明的额外参数<br> if (expected === 'number' && typeof actual !== 'number')<br> throw new TypeError(`Argument ${i} expected number, got ${typeof actual}`);<br> if (expected === 'string' && typeof actual !== 'string')<br> throw new TypeError(`Argument ${i} expected string, got ${typeof actual}`);<br> }<br> return Reflect.apply(target, thisArg, args);<br> }<br> });<br>}<br><br>const greet = typed((name, age) => `Hello ${name}, ${age} years old`, ['string', 'number']);


















