JavaScript 中的 Proxy 是一个内置的对象,用于定义基本操作的自定义行为(如属性查找、赋值、枚举、函数调用等)。Proxy 用于拦截并定义对某个对象的操作,它允许你为这些操作定义自定义的行为。简单来说,Proxy 允许你创建一个对象的“代理”,这个代理可以对外部对该对象的操作进行拦截和处理。
Proxy 对象的语法如下:
const p = new Proxy(target, handler);
target:要包装的目标对象(可以是任何类型的对象,包括原生数组、函数、甚至另一个代理)。handler:一个对象,其属性是当执行一个操作时定义行为的一组函数。
**handler** 对象可以包含以下捕获器(traps):
get(target, propKey, receiver):拦截对象属性的读取操作。set(target, propKey, value, receiver):拦截对象属性的设置操作。has(target, propKey):拦截propKey in proxy的操作。deleteProperty(target, propKey):拦截delete proxy[propKey]的操作。ownKeys(target):拦截Object.getOwnPropertyNames(proxy)、Object.getOwnPropertySymbols(proxy)、Object.keys(proxy)、for...in循环等操作。getOwnPropertyDescriptor(target, propKey):拦截Object.getOwnPropertyDescriptor(proxy, propKey)操作。defineProperty(target, propKey, propDesc):拦截Object.defineProperty(proxy, propKey, propDesc)、Object.defineProperties(proxy, propDescs)操作。preventExtensions(target):拦截Object.preventExtensions(proxy)操作。getPrototypeOf(target):拦截Object.getPrototypeOf(proxy)操作。isExtensible(target):拦截Object.isExtensible(proxy)操作。setPrototypeOf(target, proto):拦截Object.setPrototypeOf(proxy, proto)操作。apply(target, thisArg, argumentsList):拦截函数调用的操作。construct(target, argumentsList, newTarget):拦截new操作符的操作。
下面是一个简单的例子,展示了如何使用 Proxy 来拦截和自定义属性的读取和设置操作:
const handler = {
get: function(target, name) {
return name in target ? target[name] : '默认值';
},
set: function(target, name, value) {
if (name === 'age' && typeof value !== 'number') {
throw new TypeError('年龄必须是数字');
}
target[name] = value;
return true;
}
};
const person = new Proxy({}, handler);
person.name = '张三'; // 设置属性
console.log(person.name); // 读取属性,输出:"张三"
console.log(person.age); // 读取未定义的属性,输出:"默认值" person.age = 30; // 设置属性 console.log(person.age); // 输出:30 person.age = '三十'; // 尝试设置非法值,将抛出错误
在这个例子中,Proxy 对象 person 的 get 捕获器用于定义当尝试访问一个不存在的属性时的返回值,而 set 捕获器用于确保 age 属性的值是一个数字。如果尝试给 age 赋予一个非数字值,set 捕获器将抛出一个错误。