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

同分类其他题目