0

I have the following inputModel:

var UserCreateInputModel = function(req) {
    ...
    this.password = req.body.password;
    this.repeatPassword = req.body.repeatPassword;
    ...

    console.log(this.password !== this.repeatPassword);

    this.validate();
};
UserCreateInputModel.prototype = InputModel;

UserCreateInputModel.prototype.validate = function() {
    console.log('Validating...');
    if(this.password !== this.repeatPassword) throw new Error('Passwords are not equal!');
};

module.exports = UserCreateInputModel;

In my test I would like to test if the exception was thrown (using node's assert module):

//Act
assert.throws(function() {
    new UserCreateInputModel(req);
}, Error);

Somehow the exception is just not thrown. My console output from the constructor is "this". On the console I don't see the output "Validating".

I guess this is some JavaScript pitfall or something like that (about this) but I'm just not getting the error ...

Update I have another inputModel in another file. This "inherites" from InputModel too. So it seems UserCreateInputModel.prototype.validate is overridden in the other inputModel. Still don't get it ...

mosquito87
  • 4,270
  • 11
  • 46
  • 77

2 Answers2

0

This line:

UserCreateInputModel.prototype.validate = function() {
    console.log('Validating...');
    if(this.password !== this.repeatPassword) throw new Error('Passwords are not equal!');
};

is modifying the InputModel object. If you have two different types "inheriting" from InputModel with what you have here, and they both have validate methods, then one is overwriting the other.

To properly inherit from InputModel, use Object.create():

UserCreateInputModel.prototype = Object.create(InputModel.prototype);

And then call the parent constructor from your child constructor:

var UserCreateInputModel = function(req) {
    InputModel.call(this, <arguments>);

This way, when you modify UserCreateInputModel.prototype, you will only be modifying UserCreateInputModel.prototype and not anything else.

JLRishe
  • 99,490
  • 19
  • 131
  • 169
  • If `InputModel` is constructor, you forgot `.prototype` inside `Object.create`. The convenience `util.inherits` does this for you plus sets `constructor` properly. –  Feb 02 '15 at 11:17
  • @herby I am suspending disbelief and assuming that OP got it mostly right and just left out `Object.create()`. It is entirely possible that `InputModel` itself is indeed the prototype that OP wants to use – JLRishe Feb 02 '15 at 11:21
  • Hm. Naming suggests otherwise, but only OP knows for sure. In my pessimism I can even imagine even the worse scenario: that dreaded "pattern" `SubClass.prototype = new SuperClass();`, it may as well be that `InputModel` is such a full-blown instance. :-\ But it may as well be that I am just too pessimistic here. –  Feb 02 '15 at 11:30
  • 1
    @mosquito87 You've deleted the question you put here in the comments, but yes, there are disadvantages to using `new` to create a prototype. It creates a situation where every instance of the child type shares the _same instance_ of the parent type as their prototype, and this can lead to a lot of problems. You should use `Object.create` and then call the parent constructor from your child constructor. See also: http://www.bennadel.com/blog/2184-object-create-improves-constructor-based-inheritance-in-javascript-it-doesn-t-replace-it.htm – JLRishe Feb 02 '15 at 11:35
0

UserCreateInputModel.prototype = InputModel is not how you do inheritance. Who taught you this???!!!

It's:

  • after the constructor, util.inherits(UserCreateInputModel, InputModel) (where util is require('util')), and
  • inside the constructor, calling InputModel.apply(this, arguments); or InputModel.call(this, <explicit list of input model ctr args>).

Get back with another EDIT if it still persists.