javascript 为原型方法创建代理

qjp7pelc  于 2023-06-04  发布在  Java
关注(0)|答案(3)|浏览(210)

我正在摸索一种避免为每个新对象示例创建新代理的方法。我有一个原型,我只想使用一个代理。这就是目标如果我每个示例都使用一个代理,我可能会有成千上万的代理对象,这会大大降低性能。
最终,我所做的是在原型方法上设置属性,如下所示:

const v = {
  foo: function () {
    assert.notEqual(this, v);
  }
};

v.foo.bar = function(){
   // I need `this` to be a certain value here
};

v.foo.zam = function(){
   // I need `this` to be a certain value here
};

但是我需要这些属性仍然具有相同的上下文(this值),就像prototype方法本身一样。

const assert = require('assert');

const v = {
  foo: function () {
    assert.notEqual(this, v);
  }
};

new Proxy(v.foo, {
  get: function(target, prop){
     console.log(this); // I am looking to get access to `x` here
  }
});

const x = Object.create(v);

x.foo();
const z = x.foo.bar; // I would have guessed this would have fired the Proxy `get` method.

我正在尝试一些黑魔法,我可以从代理访问v原型方法的this值。在这种情况下,这意味着从代理访问x的值。这可能吗?另外,我不明白为什么当我从x.foo读取bar属性时,Proxy的get方法没有被调用,就像在x.foo.bar中一样。
我刚刚创建的Github gist更接近:https://gist.github.com/ORESoftware/757dd6285d554f4f52ae415fd39141a5
然而,我仍然认为我想做事情是不可能的。其基本原理是,我可以在原型中重用相同的Proxy对象,而不必为每个示例创建新的Proxy。

fzwojiic

fzwojiic1#

你不需要一个代理,你只需要一个简单的getter:

const v = {
  get foo() {
    console.log(this); // will log x
    return Object.assign(() => "hi", {bar: 42});
  }
};

const x = Object.create(v);

console.log(x.foo());
console.log(x.foo.bar);

其基本原理是,我可以在原型中重用相同的Proxy对象,而不必为每个示例创建新的Proxy。
为此,您需要使用代理 * 作为 * 原型。您当前的代码只是创建一个代理对象,然后将其丢弃,这不会以任何方式影响原始代码。你宁愿做一些

const p = new Proxy({}, {
  get(target, prop) {
    console.log(target); // will log x
    if (prop == "foo")
      return Object.assign(() => "hi", {bar: 42});
  }
});

const x = Object.create(p);
//                      ^ use the proxy here!

console.log(x.foo());
console.log(x.foo.bar);
piztneat

piztneat2#

也可以将代理添加到对象原型。

SomeObject.prototype = new Proxy(
    SomeObject.prototype,
    SomeObjectHandlerProxy
);

instance = new SomeObject();

应该可以

vmdwslir

vmdwslir3#

这里有一些黑魔法,但它有效,你可以使用Object.defineProperty getter为代理的原型方法设置上下文,(注意这种方法只适用于你代码的同步部分)。

const proto = {};  // the prototype object 

const ctx = {
   val: null
};

const foo = function () {
    // the prototype method
    // do something with ctx.val which gets set dynamically
};

foo.bar = function(){
  // doing important stuff here
  // do something with ctx.val which gets set dynamically
};

const p = new Proxy(foo, {
  get: function (target, prop) {

    if (typeof prop === 'symbol') {
      return Reflect.get.apply(Reflect, arguments);
    }

    // do something with ctx.val
    // => ctx.val

  }
});

Object.defineProperty(proto, 'foo', {
  get: function() {
    ctx.val = this;  // set the context here!!
    return p;
  }
});

现在我们可以这样使用它:

proto.foo.bar()

当访问foo时,它会动态地设置bar()的ctx
最后我这样使用它:

const o = Object.create(proto);
o.foo.bar();

如果需要,我们也可以调用o.foo()

相关问题