Sub.prototype = new Base () vs Sub.prototype = Base.prototype
There are many JavaScript prototypes and inheritance on the web. Most of them use code like this:
function Base() {}
function Sub() {}
with inheritance implemented like this:
Sub.prototype = new Base();
But I'm wondering what is wrong with inheritance implemented this way:
Sub.prototype = Base.prototype;
The second seems to work just as well. The only two differences I noticed (that IMO is an advantage of the second approach):
- there is another dummy instance
Base
which is obviously better as the instance is never used anyway - checking the instances shows that the first approach creates two nested ones
__proto__
and the second only one, which is what the instance cleaner does.
The latter is illustrated by the following 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:
But I have the impression that I am missing a very important point. My question is, what happens with the second approach?
When you use the same prototype, you don't inherit anything, you just create a different type that is a copy of the first.
If you put anything in an object of the base type, it won't inherit if you just get a 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);
When you add a new property to Sub.prototype
, you don't want it to affect Base.prototype
, do you? This will be very difficult.: -)
Using an approach new Base()
means that any changes you make in Sub.prototype
will not "seep" before Base.prototype
.
I would install it this way
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
If you are using Sub.prototype = Base.prototype;
, you cannot add any methods to Sub.prototype without having them in Base.prototype, because they are the same object.
Except for the constructor, Sub and Base will be exactly the same.
Basically, if you assign a property prototype
, you create a different constructor that will create objects that project the same object, not inheritance, you will see this in 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
Sample script
If we use the same object in a subtype YourCase.prototype = Base.prototype
when editing YourCase.prototype
, you are editing as well Base.prototype
, because it is the same object.
For this you need to use Object.create(Base.prototype)
or new Base()
to extend the prototype.