Skip to content

Proxy 和 Reflect 中的 receiver 到底是什么? #52

@sl1673495

Description

@sl1673495

Proxy 的 get trap 中的 receiver 是什么?

在 Reflect.get 的场景下,receiver 可以改变计算属性中 this 的指向。

var target = {
  get a() { return this.c }
}

Reflect.get(target, 'a', { c: 4 }) // 4

在 Proxy trap 的场景下,这个 receiver 永远指向 Proxy 本身或者继承它的对象。

var proxy = new Proxy({}, {
  get: function(target, property, receiver) {
    console.log(this)
    return receiver;
  }
});
proxy.getReceiver; // proxy
var inherits = Object.create(proxy);
inherits.getReceiver; // inherits

注意 get 函数里的 this 指向的是 Proxy 的第二个参数 handler 也就是 { get() { ... } } 这个对象。

在对象的计算属性里访问 this 的时候,会有用,这种情况好像没法用 call 改变指向吧。

var target = {
  get a() {
    return this.b
  }
}

Reflect.get(target, 'a', { b: 3} )

还有就是比较复杂的逻辑

var target = {
  get a() {
    return this.b
  }
}

var p = new Proxy(target, {
  get(raw, key, receiver) {
     if (key === 'b') { return 3 }
     return Reflect.get(raw, key)
  }
})

p.a // undefined

由于 target 本身没有 b 这个属性,所以访问到的是 undefined

换一个写法

var p = new Proxy(target, {
  get(raw, key, receiver) {
     if (key === 'b') { return 3 }
     // receiver就是 proxy 对象,这下应该能访问到 'b' 了吧
     return Reflect.get(receiver, key)
  }
})

p.a

VM6758:2 Uncaught RangeError: Maximum call stack size exceeded

直接死循环了,因为访问 p.a 进入 get 函数后又继续访问 p.a 无限循环。

正确写法:

var p = new Proxy(target, {
  get(raw, key, receiver) {
     if (key === 'b') { return 3 }
     return Reflect.get(raw, key, receiver)
  }
})

p.a // 3

对于 Proxy 的拦截,还是老老实实的把 receiver 传递给 Reflect.get 比较好。

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions