Reputation: 1047
Lets say I have two APIs and I would like to inherit classes from the first, but modify the response with .prototype.toJSON().
When I inherit from the first class, how can I inherit class methods as well.
An example
//file v1/models/users.js
var UserModel = function() {
this.id = 0;
this.firstName = '';
this.lastName = '';
}
UserModel.find = function(q, callback) {
//find any user that matches q and map them to UserModel
if (err) return callback(err, null);
callback(null, users);
}
module.exports = UserModel;
And the the next version
//file v2/models/users.js
var UserModel = require('../v1/models/users');
function UserModelV2() {
UserModel.call(this);
}
UserModelV2 = Object.create(UserModel.prototype);
UserModelV2.prototype.constructor = UserModel;
UserModelV2.prototype.toJSON = function() {
var obj = {};
obj.firstName = 'foo';
return obj;
}
module.exports = UserModelV2;
When I now try to call
var User = require('./v2/models/users');
User.find(1);
I get an error saying User.find does not exists.
I am aware I am only inheriting prototypal properties, but I cannot find an example of inheriting class methods anywhere.
Upvotes: 0
Views: 313
Reputation: 65806
Don't add find
directly onto UserModel
because that causes the method to be added only to one instance.
Add it to the prototype:
UserModel.prototype.find = function(id) {
//find the user by id and return
}
Because all instances of UserModel
will inherit from the prototype of your constructor function.
Then, your next version would inherit from the first like this:
// Constructor of sub-class
function UserModelV2() {
// Call the prototype.constructor, not just .constructor
UserModel.prototype.constructor.call(this);
}
// Perform inheritance
UserModelV2.prototype = new UserModel();
// Correct the constructor of the prototype
UserModelV2.prototype.constructor = UserModelV2;
// Extend the sub-class
UserModelV2.prototype.toJSON = function() {
var obj = {};
obj.firstName = 'foo';
return obj;
}
By the way (and this could be why you got stuck on this), technically (and despite the class
keyword), JavaScript does not have classes, it has prototypes and they are the basis for inheritance.
Upvotes: 3
Reputation: 12637
Well, you can simply copy the methods over from UserModel
Object.assign(UserModelV2, UserModel);
Or you define that the UserModelV2
function inherits its properties from the UserModel
function instead of Function.prototype
directly.
Object.setPrototypeOf(UserModelV2, UserModel);
Or you use the new class
syntax and let that take care of this:
class UserModelV2 extends UserModel {
toJSON(){
return {firstName: 'foo'};
}
}
maybe in combination with a transpiler like babel, if you need backwards compatibility.
I'd encourage the last option. To me this seems like the cleanest approach and provides you with the ability to not use the transpiler.
And it is semantically clear. Even the JS compiler can tell that you're not just arbitrarily messing around with the prototype of some function and may break something or do something "weird".
Upvotes: 0