Calling prototype methods from javascript constructor
I have the following simple inheritance pattern and I would like to know if it is okay to call methods the way I do inside a constructor function (mostly using this
"super prototype" instead.
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 (polycomplete I don't know very well)
Function.prototype.inherits = function(Parent) {
function ProtoCopy() {}
ProtoCopy.prototype = Parent.prototype;
this.prototype = new ProtoCopy();
this.prototype.constructor = this;
}
My pets are created this way var lion = new Lion('Simba')
In Lion's constructor,
Can I use this
sub / parent class when calling methods? Or should I use methods from the original prototype directly? (for example pseudo-call super()
or release()
)
The reasons why I am asking:
-
this
runtime substitution -
constructor
property is not always what we think (from what I read here and there)
I'm not sure how these things might affect the resulting object.
Thanks for your enlightenment!
source to share
What is the difference between using
this.fn()
andMyClass.prototype.fn.call(this)
in a constructor function?
This does not apply to constructor functions, it is the same in all functions (methods) called on instances.
In fact, there is no difference other than the number of characters when this.fn === MyClass.prototype.fn
, and they will behave exactly the same. However, this assumption is not always true - it this
may not inherit from MyClass.prototype
directly, but rather be an instance of a subclassand this subclass can be overwritten this.fn
.
So which one is correct? Both, in fact. If you know the difference, you can choose the right one for your case. Other languages have different default expectations here, see also calling static methods .
Note that you cannot replace a class reference this.constructor
that will be overwritten as well. In a sensible setting, 1this.fn()
will always be equivalent this.constructor.prototype.fn.call(this)
.
This is similar to why super calls must explicitly refer to the superclass and do not depend on instance properties (such as this.constructor
, this.super
or something similar).
1: Where this.fn
is a normal method inherited from a prototype rather than its own instance, and where each prototype has a .constructor
pointing to the corresponding constructor whose .prototype
it is.
source to share
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
source to share