记录 getter 使用代理获取的内容

Log what getter gets using proxy

我有以下记录获取事件的代理处理程序。

const proxyHandler = {
  get: function(target, prop) {
    console.log("get", prop);
    return Reflect.get(target, prop);
  }
};

const obj = new Proxy(
  {
    value: 4,
    text: "hi",
    get textVal() {
      return this.text.repeat(this.value);
    },
    getTextVal() {
      return this.text.repeat(this.value);
    }
  },
  proxyHandler
);


console.log("------- normal func -------")
console.log(obj.getTextVal());
console.log("------- getter func -------")
console.log(obj.textVal);

当我登录 console.log(obj.getTextVal()) 时,我得到:

get getTextVal 
get text 
get value 
hihihihi 

但是当我登录 getter console.log(obj.textVal) 时,我只得到以下信息:

get textVal 
hihihihi 

如何让 obj.textVal 记录 get text 并使用代理获取 get value 事件? IE。当 运行 console.log(obj.textVal) 我想要下面的结果。

get getTextVal 
get text 
get value 
hihihihi 

您可以将 Proxy 实例设置为 proxyHandler 对象并通过它访问属性(而不是 this)。

const proxyHandler = {
  get: function(target, prop) {
    console.log("get", prop);
    return Reflect.get(target, prop);
  }
};
const proxifiedObj = {
    value: 4,
    text: "hi",
    get textVal() {
      return this.proxyInstance.text.repeat(this.proxyInstance.value);
    },
    getTextVal() {
      return this.text.repeat(this.value);
    }
}

obj = proxifiedObj.proxyInstance = new Proxy(proxifiedObj, proxyHandler);



console.log("------- normal func -------")
console.log(obj.getTextVal());
console.log("------- getter func -------")
console.log(obj.textVal);    

console.log(obj.textVal);
get getTextVal 
get text 
get value 
hihihihi 

更新:

或者您可以通过创建自定义 Proxy 来为您完成作业来做同样的事情
(注意:Proxy class 不能扩展,但我们可以使用 模式):

  class InstanceAwareProxy {
      constructor(proxifiedObject, proxyHandler) {
          return proxifiedObject.proxyInstance 
                 = new Proxy(proxifiedObject, proxyHandler);
      }
  }

  obj = new InstanceAwareProxy(proxifiedObj, proxyHandler);

以上答案有效,但还有更优雅的解决方案。您在 Proxy 陷阱和 Reflect 参数中缺少 receiver 。只需将代理更改为:

const proxyHandler = {
  get: function(target, prop, receiver) {
    console.log("get", prop);
    return Reflect.get(target, prop, receiver);
  }
};

Notice the new receiver in the trap and Reflect arguments.

代理陷阱 targetreceiver 之间有一个重要区别。在这种情况下,target 是底层原始对象,而 receiver 是代理包装器。如果您不将 receiver 传递给 Reflect 调用,get 操作中的所有内容都将 运行 针对原始对象,并且不会触发代理陷阱。

如果你有时间我建议你阅读 ES6 规范的相关部分以完全掌握这两者之间的区别。否则,只要确保将 all 代理陷阱参数转发给匹配的 Reflect 调用(如果您的目标是透明包装)。