为原型方法创build代理

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

最终,我正在做的是设置一个原型方法的属性,但我需要这些属性仍然有相同的上下文( 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的值。 这是可能的吗? 另外,我不知道为什么当我从x.foo读取bar属性时,不会调用Proxy的get方法,就像在x.foo.bar

这个Github的主旨我刚刚创build了一点: https : //gist.github.com/ORESoftware/757dd6285d554f4f52ae415fd39141a5

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

你不是在寻找代理,你只需要一个简单的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); 

理由是我可以在原型中重用相同的代理对象,而不必为每个实例创build一个新的代理。

为此,您需要使用代理作为原型。 您目前的代码只是创build一个代理对象,然后把它扔掉,这不会影响原代码。 你宁愿需要做类似的事情

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

这里有一些黑魔法,但是它可以工作,你可以使用一个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时,它会dynamic设置bar的ctx()

我最终使用它是这样的:

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

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