8

I'm on my journey to learn Object-Oriented Programming in Javascript. I got this video lession from here http://www.objectplayground.com/ which I understood quite a bit the prototypal method over classical method.

While watching the lession, I was paused by the example shown for the classical method to work with subclasses which is the below:

//superclass
function Answer(value){
     this._val = value;
}

//define prototype property 'get' for the superclass
Answer.prototype.get = function fn1(){
    return this._val;
}

//subclass
function FirmAnswer(value){
    Answer.call(this,value);
}

FirmAnswer.prototype = Object.create(Answer.prototype);
FirmAnswer.prototype.constructor = FirmAnswer;

//define prototype property 'get' for subclass
FirmAnswer.prototype.get = function fn2(){
   return Answer.prototype.get.call(this);
}


var luckAnswer = new FirmAnswer(7);
luckAnswer.get(); //7

Question:

From my understanding of call function, it will set the this to the current context which is for example from this line Answer.call(this,value) from the FirmAnswer function, so the _val from Answer will be set for the FirmAnswer and not for the Answer (please correct me if I'm wrong).

So it leads me to my confusion if the above analyzation is correct, as to why the get property of the FirmAnswer.prototype returns Answer.prototype.get.call(this) and not just Answer.prototype.get() alone since the this is already set to FirmAnswer when calling new FirmAsnwer(7)?

Please shed me some light as I'm pretty confused as of the moment. I'm pretty sure I understand well the prototypal method but the classical method confuses me quite a bit.

Thank you in advance!

Roljhon
  • 1,279
  • 2
  • 9
  • 22
  • 1
    Possible duplicate of [How does JavaScript .prototype work?](http://stackoverflow.com/questions/572897/how-does-javascript-prototype-work) – Jared Smith Jan 26 '17 at 22:23

3 Answers3

1

Irrelevant since edit to question

This is weird code and contains one mistake and something else that's inexplicable.

The mistake is this line:

FirmAnswer.prototype.get = Object.create(Answer.prototype);

This is obviously nonsense code, particularly as FirmAnswer.prototype.get gets set to something far more sensible two lines later. I'm fairly sure it's meant to be:

FirmAnswer.prototype = Object.create(Answer.prototype);

That's the normal way of doing prototypal inheritance in pre-ES6 Javascript.

End irrelevance

I don't understand why FirmAnswer.prototype.get gets set to another method, when the call would be delegated to Answer.prototype.get in any case once the above error is fixed.

You asked a specific question, however: why is this line necessary:

return Answer.prototype.get.call(this);

Why can't we just do Answer.prototype.get()? When we did Answer.call(this,value);, it set the context (this value) for that call only. It only affected the constructor function. If you did Answer.prototype.get(), the context for the function call would actually be Answer.prototype, which doesn't have a _val property.

This is all irrelevant, however, because that method is not actually needed. Here's the code in a more sensible form:

//superclass
function Answer(value){
     this._val = value;
}

//define prototype property 'get' for the superclass
Answer.prototype.get = function fn1(){
    return this._val;
}

//subclass
function FirmAnswer(value){
    Answer.call(this,value);
}

FirmAnswer.prototype = Object.create(Answer.prototype);
FirmAnswer.prototype.constructor = FirmAnswer;

var luckAnswer = new FirmAnswer(7);
console.log(luckAnswer.get()); //7
lonesomeday
  • 233,373
  • 50
  • 316
  • 318
  • Sorry for this `FirmAnswer.prototype.get` I typed it wrong. my apologies – Roljhon Jan 26 '17 at 21:39
  • @Roljhon Sorry, what do you mean? – lonesomeday Jan 26 '17 at 21:40
  • I updated the code, the code is actually not like that, its simple `FirmAnswer.prototype` since its creating a prototype object for the function `FirmAnswer`, I'm sorry, my mistake, didn't noticed. – Roljhon Jan 26 '17 at 21:41
  • @Roljhon My answer still stands, although the first part is now irrelevant. I've marked it as such. – lonesomeday Jan 26 '17 at 21:49
  • I just got the code from the lesson, so that means `this` is actually set to `FirmAnswer` right? the added `Answer.prototype.get.call(this);` is the one that confused me actually since it's like redundant on that case. But thank you for clearing that out to me that it's no longer needed. So it's clearer now – Roljhon Jan 26 '17 at 22:04
  • If you want to call the `Answer.prototype` method *rather than one on `FirmAnswer.prototype`*, this is the way to do it. – lonesomeday Jan 26 '17 at 22:06
  • But i guess the original code is also be useful on some cases if you want to define the same method with a different behavior. – Roljhon Jan 26 '17 at 22:08
  • @Roljhon Yes, exactly. – lonesomeday Jan 26 '17 at 22:30
0

Now that you edit the code, there is no need to have this:

//define prototype property 'get' for subclass
FirmAnswer.prototype.get = function fn2(){
   return Answer.prototype.get.call(this);
}

because FirmAnswer.prototype already has get function when you do this:

FirmAnswer.prototype = Object.create(Answer.prototype);

it copies the get function from Answer.prototype to FirmAnswer.prototype

so, you can delete it:

//superclass
function Answer(value){
     this._val = value;
}

//define prototype property 'get' for the superclass
Answer.prototype.get = function fn1(){
    return this._val;
}

//subclass
function FirmAnswer(value){
    Answer.call(this,value);
}

FirmAnswer.prototype = Object.create(Answer.prototype);
FirmAnswer.prototype.constructor = FirmAnswer;

var luckAnswer = new FirmAnswer(7);
luckAnswer.get(); //7
tfidelis
  • 443
  • 8
  • 16
0

The function FirmAnswers constructor is passing it's this to function Answer, where Answer is setting this._val. So if you were to look at luckanswer in the console FirmAnswer { _val: 7 }

It is a FirmAnswer type object with a _val of 7

When you set FirmAnswer.prototype.get to a named anon function which returns a call to Answer.prototype.get you again are passing the FirmAnswers this to the prototype which is basically making a copy of the protoype.

JellyKid
  • 302
  • 1
  • 6
  • I think our understanding is the same from how the context of `FirmAnswer` was passed to `Answer`, however, from that point of view which I pointed out on my question. Why not just use `Answer.prototype.get()` instead `Answer.prototype.get.call(this)`? then? since `this` is already assigned to `FirmAnswer`, so `call` from my understanding is not needed since why do we need to set the context to `FirmAnswer` if it's already set? – Roljhon Jan 26 '17 at 21:48