Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the correct prototype affectation in javascript inheritance?

I read several articles on js inheritance already (this one, this one, this one, etc.)

In this article from Mozilla, "classic" inheritance is shown as this : (I uniformized examples)

// inherit Base
function Derived() { ... }
Derived.prototype = new Base();            <-------
Derived.prototype.constructor = Derived;   <-------

However in this article I see :

// inherit Base
function Derived() { ... }
Derived.prototype = Object.create(Base.prototype);    <-------
Derived.prototype.constructor = Derived;

Moreover I have also seen this :

Derived.prototype = Base.prototype;

And I also experimented and couldn't find the use of constructor affectation :

Derived.prototype.constructor = Derived; <--- it still work if I skip this line

if I skip this line, new Derived() correctly calls Derived() anyway.

So 1) what is correct :

  1. Derived.prototype = new Base();
  2. Derived.prototype = Object.create(Base.prototype);
  3. Derived.prototype = Base.prototype;
  4. other ?

And 2) is Derived.prototype.constructor = Derived; really needed ? Why ?

like image 286
Offirmo Avatar asked Oct 02 '22 04:10

Offirmo


2 Answers

Derived.prototype = new Base();

This does call the Base constructor just for setting up the prototype chain. While sometimes working and giving equivalent results to Object.create, it is error-prone and should be avoided. Read What is the reason to use the 'new' keyword at Derived.prototype = new Base (and why it should not be used).

Derived.prototype = Object.create(Base.prototype);

This is state of the art - Correct javascript inheritance so to say.

Derived.prototype = Base.prototype;

This is plain wrong. Do not use. It lets Base and Derived instances inherit from the same object - while it (seldom) can be helpful to have multiple constructors for a "class", this is not "subclassing".

Is Derived.prototype.constructor = Derived; really needed? Why?

It can be omitted and your script will work nonetheless, but for convenience you would expect that (new Derived).constructor === Derived. Also have a look at JavaScript inheritance and the constructor property

like image 179
Bergi Avatar answered Oct 09 '22 20:10

Bergi


What is the correct way to do classical inheritance in JavaScript

In this answer i explained the difference between 1 and 2 showing why 2 is the best way to emulate classical inheritance in JavaScript.

In short, in solution 1 children inherit from an instance of the parent. In solution 2 the class of the children (Derived.prototype) inherits from the class of the parent(Base.prototype). This imposes severe limitations on the parent, because it must be called with 0 arguments.

The 3rd solution is even worse because the prototypes of the Derived and the Base class are the same object, so no method overriding can take place. Even worse, a method defined in Derived.prototype will be available for all Base instances and if a method with the same name had been declared on Base.prototype, it would simply be replaced.

Conclusion: 2 is the true way to do classical inheritance in JavaScript.

Is setting the constructor property needed

Setting the constructor property on the prototype makes it accessible to all instances. That is simply for convenience, the inheriting part works without it.

like image 28
Tibos Avatar answered Oct 09 '22 20:10

Tibos