Reputation: 6172
Making a simple ORM with ES6 classes, I run with a blocking issues – I can't properly copy a class (as I would have with util.extend
in ES5).
Specifically, here is what I tried:
class BaseModel {
echo() {
console.log(this.props);
}
static _setProperties(props) {
this.props = props;
}
}
function makeModel(props) {
// Try to copy the Class object
const Model =
Object.assign(Object.create(Object.getPrototypeOf(BaseModel)), BaseModel);
// Copy my static methods – is there a better way to do this?
Object.getOwnPropertyNames(BaseModel).forEach((key) => {
if (!key.startsWith('_')) return;
Model[key] = BaseModel[key];
});
// Configure the new model
Model._setProperties(props);
return Model;
}
const GreeterModel = makeModel('hello');
const greeter = new GreeterModel();
greeter.echo(); // Should log hello
The error I get is:
TypeError: GreeterModel is not a constructor
Is there any way to achieve this with ES6 classes, or do I have to stick to ES5-style?
Optional question: is there a better way to copy the static methods? The solution with getOwnPropertyNames
is not ideal as it returns also read-only properties, such as length
.
Thanks!
Upvotes: 2
Views: 1183
Reputation: 816522
There is a logic mistake in your base class. this
always depends on how a function is called. A static function is usually called on the constructor, i.e. BaseModel._setProperties(...)
in which case this
refers to BaseModel
.
Instance methods however are called on an the instance itself, therefore this
refers to the instance not the constructor.
To make BaseModel
work you would have to use
echo() {
console.lof(this.constructor.props);
}
But to answer your actual question, you can simply extend the class:
function makeModel(props) {
class Model extends BaseModel {}
Model._setProperties(props);
return Model;
}
Note that this is isn't "cloning" the base class, it's extending it. There is no reasonable way to clone a function in JavaScript (not so far fat least).
Upvotes: 5