代理对象 - 从 getter 属性中访问目标?

范诺姆

我有一个简单的代理对象:

const myProxy = new Proxy(
  /* myTarget */
  {
    test: 2,
  },
  /* myHandler */
  {
    get(target, prop, proxy)
    {
      if (prop in this && this[prop] instanceof Function)
        return this[prop](target); //getter

      return target[prop]; //value
    },
    
    myGetter(target)
    {
      return ++target.test
    }
  }
);

console.log("test before", myProxy.test);
console.log("myGetter", myProxy.myGetter);
console.log("test after", myProxy.test);

有没有办法让myGetter财产成为真正的吸气剂?我的尝试失败了,因为我不知道如何myTarget从 getter 中访问:

const myProxy = new Proxy(
  /* myTarget */
  {
    test: 2,
  },
  /* myHandler */
  {
    get(target, prop, proxy)
    {
      if (prop in this)
        return this[prop]; //getter

      return target[prop]; //value
    },
    
    get myGetter()
    {
      return ++target.test; //target undefined
    }
  }
);

console.log("test before", myProxy.test);
console.log("blah", myProxy.myGetter);
console.log("test after", myProxy.test);

我需要这个的原因是因为我在处理程序中有多个函数,我需要确定哪一个需要在处理程序本身内执行(myGetter),或者应该作为函数引用(myFunc)返回,它还可以接受额外的数据作为参数,所以我prop instanceof Function用来检查它是否是一个函数:

const myProxy = new Proxy(
  /* myTarget */
  {
    test: 2,
  },
  /* myHandler */
  {
    get(target, prop, proxy)
    {
      if (prop in this)
      {
        if (this[prop] instanceof Function)
          return (args) => this[prop](target, args); //function

        return this[prop]; //getter
      }
      return target[prop]; //value
    },
    
    get myGetter()
    {
      return ++target.test; //target undefined
    },

    myFunc(target, value)
    {
      return target.test * value;
    }
  }
);

console.log("myFunc", myProxy.myFunc(3));
console.log("test before", myProxy.test);
console.log("myGetter", myProxy.myGetter);
console.log("test after", myProxy.test);

我可以想到几种解决方法,例如函数的硬代码名称:

const myProxy = new Proxy(
  /* myTarget */
  {
    test: 2,
  },
  /* myHandler */
  {
    get(target, prop, proxy)
    {
      if (prop in this)
      {
        if (["myFunc"].includes(prop)) // function
          return (args) => this[prop](target, args);

        return this[prop](target); // getter
      }
      return target[prop];
    },
    
    myGetter(target)
    {
      return ++target.test
    },

    myFunc(target, value)
    {
      return target.test * value;
    }
  }
);

console.log("myFunc", myProxy.myFunc(3));
console.log("test before", myProxy.test);
console.log("myGetter", myProxy.myGetter);
console.log("test after", myProxy.test);

或将功能分成组:

const myProxy = new Proxy(
  /* myTarget */
  {
    test: 2,
  },
  /* myHandler */
  {
    get(target, prop, proxy)
    {
      if (prop in this._myFuncs)
        return (args) => this._myFuncs[prop](target, args);

      if (prop in this._myGetters)
        return this._myGetters[prop](target);

      return target[prop];
    },
    
    _myGetters:
    {
      myGetter(target)
      {
        return ++target.test
      },
    },

    _myFuncs:
    {
      myFunc(target, value)
      {
        return target.test * value;
      },
    }
  }
);

console.log("myFunc", myProxy.myFunc(3));
console.log("test before", myProxy.test);
console.log("myGetter", myProxy.myGetter);
console.log("test after", myProxy.test);

出于教育目的,有什么建议可以让真正的吸气剂在 Proxy 中工作吗?

一定的表现

我认为处理程序对象上不应该有非标准的属性——它只具有预期具有的陷阱会更有意义。要收集陷阱的属性,要么对这些属性进行硬编码(不灵活且不太好),要么为这些属性使用单独的对象结构。在代理闭包中使用一个单独的对象,检查该属性是否存在于该对象上,然后.call如果它是一个 getter,则使用 target 对其进行操作很容易。

const makeProxy = (target, customProperties) => {
  return new Proxy(
    target, {
      get(target, prop, proxy) {
        if (prop in customProperties) {
          // Invoke getter if it exists on customProperties
          const { get } = Object.getOwnPropertyDescriptor(customProperties, prop);
          if (get) {
            return get.call(target);
          }
        }
        // Otherwise return original object value or getter
        return target[prop];
      },
    }
  );
};

const proxy = makeProxy({
  test: 2,
}, {
  get myGetter() {
    return ++this.test
  }
});

console.log("test before", proxy.test);
console.log("blah", proxy.myGetter);
console.log("test after", proxy.test);

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章