为原型方法创建代理

时间:2017-12-13 05:24:44

标签: javascript node.js proxy

我正在摸索避免为每个新对象实例创建新代理的方法。我有1个原型,我只想使用1个代理。这就是目标。如果我为每个实例使用一个代理,我可能会有成千上万的代理对象,这会严重损害性能。

最终我正在做的是在原型方法上设置属性,如下所示:

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值),就像原型方法本身一样。

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的值。这有可能吗?此外,我无法弄清楚当我从bar读取x.foo属性时未调用代理的get方法的原因,如x.foo.bar

我刚刚创建的这个Github要点更接近: this article

然而,我仍然认为不可能做我想做的事情。基本原理是我可以在原型中重用相同的Proxy对象,而不必为每个实例创建一个新的Proxy。

3 个答案:

答案 0 :(得分:1)

你不是在寻找代理人,你需要的只是一个简单的吸气剂:

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);

答案 1 :(得分:0)

这里有一些黑魔法,但是它有效,你可以使用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()

答案 2 :(得分:0)

您还可以将代理添加到对象原型中。

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

instance = new SomeObject();

类似的东西应该工作