Proxy 和 Reflect 是什么?有什么应用场景?
Proxy
Proxy 用于创建一个对象的代理,可以拦截对该对象的基本操作(属性查找、赋值、枚举、函数调用等)。
const handler = {
get(target, key, receiver) {
console.log(`读取 ${key}`)
return Reflect.get(target, key, receiver)
},
set(target, key, value, receiver) {
console.log(`设置 ${key} = ${value}`)
return Reflect.set(target, key, value, receiver)
}
}
const proxy = new Proxy({ name: 'Tom', age: 25 }, handler)
proxy.name // 打印: 读取 name
proxy.age = 26 // 打印: 设置 age = 26常用拦截器(Trap)
| Trap | 拦截操作 |
|---|---|
get |
属性读取 obj.key |
set |
属性设置 obj.key = val |
has |
in 操作符 |
deleteProperty |
delete 操作符 |
ownKeys |
Object.keys() |
apply |
函数调用 |
construct |
new 操作符 |
Reflect
Reflect 提供与 Proxy trap 对应的静态方法,使操作更加规范:
Reflect.has(obj, 'key') // 等同于 'key' in obj
Reflect.get(obj, 'key') // 等同于 obj.key
Reflect.set(obj, 'key', v) // 等同于 obj.key = v
Reflect.ownKeys(obj) // 等同于 Object.keys(obj)
Reflect.deleteProperty(obj, 'key') // 等同于 delete obj.key应用场景
1. Vue 3 响应式系统
function reactive(target) {
return new Proxy(target, {
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
}
})
}2. 数据校验
const validator = new Proxy({}, {
set(target, key, value) {
if (key === 'age' && (value < 0 || value > 150)) {
throw new RangeError('无效年龄')
}
return Reflect.set(target, key, value)
}
})3. 私有属性保护
Proxy vs Object.defineProperty
- Proxy 能监听新增属性,defineProperty 不能
- Proxy 能监听数组操作,defineProperty 不能(需要 hack)
- Proxy 性能更好,是 Vue 3 的核心改进