Reputation: 744
I have the following simple inheritence pattern and I would like to know if it's ok to call methods the way i do from within the constructor function (basically speaking, using this
instead of "super prototype".
Parent class, Pet
function Pet(name) {
this.name = name;
this.nickname = name;
this.adopt();
}
Pet.prototype.adopt = function() {
this.nickname = 'Cutty ' + this.name;
}
Pet.prototype.release = function() {
this.nickname = null;
}
Pet.prototype.cuddle = function() {
console.log(this.name + ' is happy');
}
Subclass, Lion
function Lion(name) {
Pet.prototype.constructor.apply(this, arguments); // super(name)
this.cuddle();
this.release();
}
Lion.inherits(Pet);
Lion.prototype.adopt = function() {
// DTTAH
}
Lion.prototype.release = function() {
Pet.prototype.release.call(this);
console.log('Thanks for releasing ' + this.name);
}
inherits
helper (polyfills are bad I know)
Function.prototype.inherits = function(Parent) {
function ProtoCopy() {}
ProtoCopy.prototype = Parent.prototype;
this.prototype = new ProtoCopy();
this.prototype.constructor = this;
}
My pets are instantiated like so var lion = new Lion('Simba')
In Lion constructor,
Can I keep using this
when calling sub/parent class methods ? Or should I use methods from parent prototype directly ? (like pseudo call to super()
or in release()
)
Reasons why I am asking are:
this
substitution at runtimeconstructor
property not always what we are thinking (from what I read here and there)I am not sure how these things can influence the resulting object.
Thanks for your enlightenment !
Upvotes: 3
Views: 531
Reputation: 832
Simplifying the problem, consider the following code in ES6:
class Pet {
constructor (name) {
this.name = name;
this.talk();
}
talk () {
console.log('My name is ' + this.name);
}
}
class Lion extends Pet {
constructor (name) {
super(name);
}
talk () {
super.talk();
console.log('I am a lion.');
}
}
would be equivalent to:
function Pet (name) {
this.name = name;
this.talk();
}
Pet.prototype.talk = function () {
console.log('My name is ' + this.name);
};
function Lion (name) {
Pet.call(this, name);
}
// inheritance:
Lion.prototype = Object.create(Pet.prototype);
Lion.prototype.constructor = Lion;
// override .talk
Lion.prototype.talk = function () {
Pet.prototype.talk.call(this);
console.log('I am a lion');
}
Running new Lion('Bobby')
logs:
My name is Bobby
I am a lion
Further reading: http://eli.thegreenplace.net/2013/10/22/classical-inheritance-in-javascript-es5
Upvotes: 1
Reputation: 664548
What is the difference between using
this.fn()
andMyClass.prototype.fn.call(this)
in a constructor function?
This is not specific to constructor functions, it's the same in all functions (methods) that are called on instances.
Indeed there's not much difference apart from the character count when this.fn === MyClass.prototype.fn
, and they would behave exactly the same. However, this assumption is not always true - this
might not inherit from MyClass.prototype
directly, but rather be a subclass instance, and that subclass might have overwritten the this.fn
method.
So which one is correct? Both, in fact. If you know the difference, you can choose the appropriate one for your case. Other languages have different default expectations here, see also for calling static methods.
Notice that you cannot replace the class reference by this.constructor
, which would be overwritten as well. In a reasonable setup1, this.fn()
would be always equivalent to this.constructor.prototype.fn.call(this)
.
This is similar to the reason why super calls must explicitly reference the super class, and not depend on instance properties (such as this.constructor
, this.super
or anything similar).
1: Where this.fn
is a usual method inherited from the prototype, not an own instance-specific one, and where every prototype has the .constructor
pointing to the respective constructor whose .prototype
it is.
Upvotes: 1