4

There are many resources online about JavaScript prototyping and inheritance. Most of which use code similar to this:

function Base() {}
function Sub() {}

with inheritance implemented like this:

Sub.prototype = new Base();

But I am wondering what is wrong with inheritance implemented this way instead:

Sub.prototype = Base.prototype;

It seems like the second is working just as well. The only two differences that I've spotted (which IMO are advantages of the second approach) are:

  • there is one less dummy instantiation of Base, which is obviously better as the instance is never used anyway
  • inspecting instances shows that the first approach produces two nested __proto__ properties whereas the second only single one, which makes the instance cleaner.

The latter is illustrated in below code snippet:

function Base(){}
Base.prototype.bogus = function(){};
function SubNew(){}
function SubProto(){}

SubNew.prototype = new Base();
SubProto.prototype = Base.prototype;

var sn = new SubNew();
var sp = new SubProto();

console.log(sn);
console.log(sp);

gives:

code snippet output

But I'm under the impression that I'm missing some very important point here. My question is: what is the case against the second approach?

Maciej Sz
  • 11,151
  • 7
  • 40
  • 56
  • A Dog is an Animal (Child is Parent) but an Animal is not a Dog as it can be a Cat or Fish. You should not create an instance of Parent to set as prototype of Child, better to use Object.create instead to prevent Parents instance specific members being on Child.prototype http://stackoverflow.com/questions/16063394/prototypical-inheritance-writing-up/16063711#16063711 – HMR Oct 26 '14 at 10:12

5 Answers5

4

When you add a new property to Sub.prototype, you wouldn't want it to affect Base.prototype, would you? That would be pretty broken. :-)

Using the new Base() approach means that any changes you make to Sub.prototype won't "leak through" to Base.prototype.

C. K. Young
  • 219,335
  • 46
  • 382
  • 435
  • Its better to not use new Base either, better to use Object.create to set prototype and polyfil it if you have to support old browsers – HMR Oct 26 '14 at 10:14
4

I would set it up like this

function Base() {}

function Sub() {
  // call parent constructor; optional
  Base.call(this);
}

Sub.prototype = Object.create(Base.prototype, {constructor: {value: Sub}});

This is very similar to how util.inherits works in node.js

Mulan
  • 129,518
  • 31
  • 228
  • 259
3

If you use Sub.prototype = Base.prototype; you can not add any methods to Sub.prototype without having them appear in Base.prototype, because they are the same object.
Except for the constructor, Sub and Base will be exactly the same class.

Troido
  • 78
  • 6
2

When you use the same prototype, you are not inheriting anything, you are just making another type that is a copy of the first.

If you put anything in the base type object, it won't be inherited if you just get the prototype:

function Base(){
  this.answer = 42;
}

function SubNew(){}
function SubProto(){}

SubNew.prototype = new Base();
SubProto.prototype = Base.prototype;

var sn = new SubNew();
var sp = new SubProto();

// show result in StackOverflow snippet
document.writeln(sn.answer);
document.writeln(sp.answer);
Guffa
  • 687,336
  • 108
  • 737
  • 1,005
0

Basically if you assign the prototype property you're creating another constructor that will create objects that prototype the same object, not an inheritance, you will see it clear with this example:

function Base() { }
function SubType() { }
function YourCase() { }

SubType.prototype = Object.create(Base.prototype);
YourCase.prototype = Base.prototype;

Base.prototype.foo = 1;
SubType.prototype.foo = 2;
YourCase.prototype.foo = 3;

console.log(new Base().foo); // 3 WAT?
console.log(new SubType().foo); // 2
console.log(new YourCase().foo); // 3

Fiddle example

If we use the same object on the sub type YourCase.prototype = Base.prototype when you edit YourCase.prototype you're also editing Base.prototype because they are the same object.

That's why you have to use Object.create(Base.prototype) or new Base() to extend a prototype.

A. Matías Quezada
  • 1,886
  • 17
  • 34