Skip to content

Reflect

错误示范:直接使用target[key]

js
const parent = {
  name: 'parent',
  get alias() {
    return this.name
  }
}

const proxy = new Proxy(parent, {
  get(target, p, receiver) {
    return target[p]
  }
})

const child = {
  name: 'child'
}

Object.setPrototypeOf(child, proxy) // child 继承自 proxy

console.log(child.alias) // 输出 parent 但预期应该是 child

原因:当调用child.alias时,由于child自身没有这个属性,它会去原型链找。在proxyget中,如果你返回target[key],那么parent里 的getter函数的this就会指向target(即parent对象)

正确示范:使用Reflect.get

js
const proxy = new Proxy(parent, {
  get(target, key, receiver) {
    // 传入 receiver,确保 getter 里的 this 指向调用者 child
    return Reflect.get(target, key, receiver)
  }
})

// ... 同样的继承代码
console.log(child.alias) // 输出 "Child",正确!

Reflect.get(target, key, receiver)的第三个参数可以把正确的this上下文(即receiver)传递给底层的getter函数,

让操作值拥有"状态"返回值

  • 赋值操作(set):proxy的set陷阱要求必须返回一个布尔值(成功为true,失败为false
    • 直接操作target[key] = value返回的是value本身
    • Reflect.set(target, key, value, receiver)返回的是布尔值,完全符合Proxy的规范
  • 删除操作(deleteProperty
    • 直接操作delete target[key]在严格模式下可能会报错
    • Reflect.deleteProperty(target, key)会返会一个布尔值表示是否删除成功