I'm proxying methods using the following wrapper:
public static wrap(target) {
function construct(constructor, args) {
const c: any = function(this) {
return constructor.apply(this, args);
};
c.prototype = constructor.prototype;
return new c();
}
const f = (...args) => {
const instance = construct(target, args);
const descriptors = getMethodDescriptors(target, instance);
return new Proxy<T>(
instance,
new SomeProxyHandler(descriptors)
);
};
f.prototype = target.prototype;
return f;
}
This has worked well when wrapping classes which are compiled down to ES5 but now I'm trying to target ES6 I'm getting errors at constructor.apply(this, args)
saying that:
TypeError: Class constructor OneOfMyClasses cannot be invoked without 'new'
How can I fix this code so wrap
can proxy classes whatever the JavaScript target and maintain the correct prototype chain?
ES6 implements intercession form of meta programming using Proxies. Similar to ReflectAPI, the Proxy API is another way of implementing meta programming in ES6. The Proxy object is used to define custom behavior for fundamental operations. A proxy object performs some operations on behalf of the real object.
So Proxy is a wrapper which can be used to intercept fundamental operations like [[Get]] and [[Set]] on an object whereas Reflect provides us minimal wrappers around these fundamental operations like [[Get]] and [[Set]] so that we can call them directly (Usually from inside the trap).
Every object in JavaScript has a built-in property, which is called its prototype. The prototype is itself an object, so the prototype will have its own prototype, making what's called a prototype chain. The chain ends when we reach a prototype that has null for its own prototype.
This can be done using the extends and super keywords. We use the extends keyword to implement the inheritance in ES6. The class to be extended is called a base class or parent class. The class that extends the base class or parent class is called the derived class or child class.
The easiest way would be spread syntax
const instance = new target(...args);
but you can also use Reflect.construct
:
const instance = Reflect.construct(target, args);
This will even be necessary if your wrapped classes are supposed to be extensible, you then will have to make use of new.target
:
const instance = Reflect.construct(target, args, new.target);
Btw, your f
wrapper should be a proper function
not an arrow function, as those cannot be called with new
(and don't have new.target
). Or maybe even simpler (working better with static methods and inheritance), just wrap the whole target
class itself in a Proxy
and use its construct
trap.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With