如何在维护原型链的同时在javascript中使用代理来捕获构造函数?
我想创建一个构造函数对象,该继承对象的继承工作正常,但是要捕获该构造函数,以便可以操纵该实例对象。使用 Proxy()
几乎可以解决此问题,但这似乎搞砸了继承。请注意以下没有代理的示例:
I want to create a constructor object whose inheritance works as normal, but capture the constructor so I can manipulate the instance object. Using Proxy()
almost solves this, but it seems to screw up the inheritance. Note the following example without a proxy:
> const B = function() {}
undefined
> B.name
'B'
> class C extends B {}
[Function: C]
> B.prototype == C.prototype.__proto__
true
> var instance = new C()
undefined
> C.prototype == instance.__proto__
true
> instance.__proto__
C {}
现在,如果我添加代理来捕获 construct(target,args)
,它会正确捕获构造函数,但不会像没有代理一样完全保留事物。请注意,构造函数所做的只是向控制台打印一条消息,指出其捕获情况。但是,否则(我认为)它应该做出相同的反应。但是,当我创建一个类来扩展代理功能时,似乎扩展功能完全丢失了。请注意,最后四行给出的结果与上述结果不同。
Now, if I add a proxy to capture construct(target,args)
, it will correctly capture the constructor, but it doesn't preserve things exactly as it would without the proxy. Note that all the constructor does is print a message to the console noting its capture. But otherwise (I think) it should react the same. However, when I create a class to extend the proxied function, it seems like the extended function is missing entirely. Note the last four lines give different results than above.
> const handler = { construct(target,args) {
... console.log('Captured!'); return new target(...args); } }
undefined
> const proxy_B = new Proxy(B, handler)
undefined
> proxy_B.name
'B'
> class C2 extends proxy_B {}
[Function: C2]
> proxy_B.prototype == C2.prototype.__proto__
true
> var instance2 = new C2()
Captured!
undefined
> C2.prototype == instance2.__proto__
false
> instance2.__proto__
B {}
我在做什么错?
您的处理程序无法处理 new.target
。请注意,您代理的目标
是 B
,并且当您返回新目标
,那么您将构造一个 B
实例,而不是一个 C
实例。
Your handler doesn't handle the new.target
. Notice that the target
of your proxy is B
, and when you return new target
then you'll construct a B
instance not a C
instance.
不是使用 new
来近似构造行为,而是使用 Reflect
对象(在特定的 Reflect.construct
)来使用 exact 默认构造行为并传递trap方法的所有参数:
Instead of approximating the construction behaviour with new
, use the Reflect
object (in particular Reflect.construct
) to use the exact default construction behaviour and pass all the arguments of the trap method:
const handler = {
construct(target, args, newtarget) {
// ^^^^^^^^^
console.log('Captured!');
return Reflect.construct(target, args, newtarget);
// ^^^^^^^^^
}
};