Proxy 和 Reflect 有什么用?如何实现数据劫持?
请说明 Proxy 和 Reflect 的用途、常用拦截操作,以及如何用 Proxy 实现响应式数据(类似 Vue 3)。
回答
专业代码师
Proxy:创建一个对象的代理,拦截并自定义对象的底层操作(属性读取、赋值、函数调用等)。
Reflect:与 Proxy 的 handler 方法一一对应的静态方法集合,提供操作对象的默认行为。
常用拦截操作:
const handler = {
get(target, prop, receiver) {
console.log(`读取 ${prop}`);
return Reflect.get(target, prop, receiver);
},
set(target, prop, value, receiver) {
console.log(`设置 ${prop} = ${value}`);
return Reflect.set(target, prop, value, receiver);
},
has(target, prop) { return Reflect.has(target, prop); },
deleteProperty(target, prop) { return Reflect.deleteProperty(target, prop); },
ownKeys(target) { return Reflect.ownKeys(target); }
};
实现响应式(简化版 Vue 3):
function reactive(target) {
const handler = {
get(target, key, receiver) {
track(target, key); // 依赖收集
return Reflect.get(target, key, receiver);
},
set(target, key, value, receiver) {
const result = Reflect.set(target, key, value, receiver);
trigger(target, key); // 派发更新
return result;
}
};
return new Proxy(target, handler);
}
Proxy vs Object.defineProperty: | 特性 | Proxy | defineProperty | |------|-------|---------------| | 拦截范围 | 13 种操作(get/set/has/delete/apply 等) | 仅 get/set | | 数组拦截 | 完美支持(length 变更、索引赋值) | 需重写数组方法 | | 新增属性 | ✅ 自动检测 | ❌ 需手动 observe | | 性能 | 较优(惰性代理) | 初始化成本高 |