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 {}
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 {}
What am I doing wrong? How do I write the proxy to properly handle this case?
Your handler doesn't handle the
new.target
. Notice that thetarget
of your proxy isB
, and when youreturn new target
then you'll construct aB
instance not aC
instance.Instead of approximating the construction behaviour with
new
, use theReflect
object (in particularReflect.construct
) to use the exact default construction behaviour and pass all the arguments of the trap method: