I'm currently needing to pass a class through a variable to a function which dynamically calls their constructor and so on. Short example:
class MyClass {
constructor ($q) {
console.log($q);
}
expose () {
return {};
}
}
const myclass = function () {
// My concern is this ------.
// I need to pass it |
// as a variable \|/
// '
let obj = Object.create(MyClass.prototype);
obj.constructor.apply(obj, arguments);
return {}; // other stuff goes here
};
myclass.$inject = ['$q'];
export {myclass};
My idea is to pass MyClass as a variable, to have it this way:
const myclass = function (classVariable) {
let obj = Object.create(classVariable.prototype);
obj.constructor.apply(obj, arguments);
return {}; // other stuff goes here
};
So that I can call it like let newclass = myclass(MyClass);
. This way if I have different classes (MyClass2, MyClass3, and so on) I don't have to repeat code in each file. If I try to do it this way though, Chrome throws an error saying that it cannot use a class as variable or something like that.
So, what would be the best approach to do this and avoid repeating code? it's actually a redesign I'm working on to avoid the copy-paste disaster made by someone else I need to fix. Thanks in advance!
I think your confusion is that you think that class constructors cannot be referenced by variables. They can, they're just functions. So:
class Foo {
message() {
console.log("I'm a Foo");
}
}
class Bar {
message() {
console.log("I'm a Bar");
}
}
function test(C) {
let obj = new C();
obj.message(); // "I'm a Foo" or "I'm a Bar", depending on
// whether Foo or Bar was passed in
}
test(Foo);
test(Bar);
Your pattern of calling var obj = Object.create(X.prototype)
followed by X.apply(obj, /*...args here...*/)
would work in ES5 and earlier, but ES2015's classes don't allow it. To construct instances from them, you have to use the new
operator. The reason for that has to do with subclassing and setting new.target
, so that if the instance has reason to create new instances (as Promise
does), it can do that in an unambiguous way.
Which seems like it could be a step back, but if for some reason you have the constructor arguments as an array rather than discrete items, spread notation lets you use new
anyway:
let obj = new C(...args);
So if you need a generic function that accepts a class constructor and an array of arguments and needs to return an instance of that class using those arguments, it would look like this:
function createInstanceOf(C, args) {
return new C(...args);
}
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