简体   繁体   中英

Inheriting class methods Javascript

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.

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.

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".

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM