Reputation: 1783
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?
Upvotes: 6
Views: 1996
Reputation: 664484
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.
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);
// ^^^^^^^^^
}
};
Upvotes: 11