Proxy 是 ES6 引入的一个新特性,它允许你定义一个对象的行为,拦截对对象的操作,比如读取属性、设置属性、删除属性、函数调用等。
let proxy = new Proxy(target, handler);
target是目标对象,即你希望操作的对象。handler是一个对象,其中定义了各种拦截操作,比如get、set、deleteProperty等。- 示例:
const proxy = new Proxy(target, {
get(target, prop) { return Reflect.get(target, prop); }
});
基本方法
1 捕获对象的读取操作(get)
通过 get 方法,你可以拦截对对象属性的读取。
const target = {
message: 'Hello, world!',
};
const handler = {
get(target, prop) {
if (prop in target) {
return `Intercepted: ${target[prop]}`;
} else {
return `Property ${prop} does not exist`;
}
}
};
const proxy = new Proxy(target, handler);
console.log(proxy.message); // 输出: Intercepted: Hello, world!
console.log(proxy.nonExistent); // 输出: Property nonExistent does not exist
- 当你读取
proxy.message时,get捕获了这个操作,并返回自定义的结果。 - 如果属性不存在,
get可以自定义返回值。
2 捕获对象的设置操作(set)
通过 set 方法,你可以拦截对对象属性的赋值操作。
const target = {};
const handler = {
set(target, prop, value) {
console.log(`Setting ${prop} to ${value}`);
target[prop] = value; // 默认将值设置到目标对象
return true; // 表示操作成功
}
};
const proxy = new Proxy(target, handler);
proxy.name = 'Alice'; // 输出: Setting name to Alice
console.log(target.name); // 输出: Alice
- 在这里,每次你向
proxy对象设置属性时,都会触发set方法,输出日志。
3 捕获对象的删除操作(deleteProperty)
deleteProperty 方法允许你拦截对对象属性的删除操作。
const target = {
name: 'Alice'
};
const handler = {
deleteProperty(target, prop) {
if (prop === 'name') {
console.log('Cannot delete name property');
return false; // 阻止删除
}
delete target[prop];
return true; // 允许删除
}
};
const proxy = new Proxy(target, handler);
delete proxy.name; // 输出: Cannot delete name property
delete proxy.age; // 删除成功
console.log(target); // 输出: { name: 'Alice' }
- 如果试图删除
name属性,deleteProperty方法阻止了这个操作,并输出一条消息。
4 捕获函数调用(apply)
Proxy 也可以用来拦截函数调用,控制函数的行为。
const target = function(message) {
return `Hello, ${message}`;
};
const handler = {
apply(target, thisArg, argumentsList) {
console.log(`Called with arguments: ${argumentsList}`);
return target.apply(thisArg, argumentsList); // 调用原始函数
}
};
const proxy = new Proxy(target, handler);
console.log(proxy('World')); // 输出: Called with arguments: World
// 输出: Hello, World
- 每次调用
proxy时,都会先触发apply方法,在这里你可以做一些操作(如日志记录),然后再调用原始的函数。
拦截方法
-
get(target, prop):拦截对属性的读取操作。 -
set(target, prop, value):拦截对属性的赋值操作。 -
has(target, prop):拦截in操作符。 -
deleteProperty(target, prop):拦截delete操作符。 -
apply(target, thisArg, argumentsList):拦截函数调用。 -
construct(target, args):拦截new操作符。 -
ownKeys(target):拦截对象的键操作(如Object.keys()、for...in)。 -
getOwnPropertyDescriptor(target, prop):拦截Object.getOwnPropertyDescriptor()操作。
与 Object.defineProperty (Vue2 中的做法)对比:
Proxy 支持更全面的拦截,适用于复杂场景(如数据绑定、日志记录);defineProperty 仅限属性操作。