Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

calling prototype methods from javascript constructor

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 runtime
  • constructor 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 !

like image 272
Jordan Avatar asked May 09 '26 12:05

Jordan


2 Answers

What is the difference between using this.fn() and MyClass.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.

like image 147
Bergi Avatar answered May 11 '26 03:05

Bergi


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

like image 44
deleted user Avatar answered May 11 '26 04:05

deleted user