Reputation: 13510
I'm learning JS prototypes.
From Java
language point I expect,that SpecificRectangle
object will have access to area()
method,due to area() is the method of its parent(Rectangle class) prototype.
function Rectangle(w,h){
this.width = w;
this.height=h;
}
Rectangle.prototype.area = function(){return this.width*this.height}
function SpecificRectangle(w,h,angle){
Rectangle.call(this,w,h);
SpecificRectangle.prototype=new Rectangle();
}
var specrec = new SpecificRectangle(7,8,45);
All at all I can't call area()
method on SpecificRectangle
instance.
Standard JS error got:
TypeError: specrec.area is not a function
[Break On This Error] specrec.area()
What is the explanation and reason of such encapsulation?
Upvotes: 3
Views: 3431
Reputation: 16140
You should copy base class prototype. Eg:
function Rectangle(w,h){
this.width = w;
this.height=h;
}
Rectangle.prototype.area = function(){return this.width*this.height}
function SpecificRectangle(w,h,angle){
Rectangle.call(this,w,h);
}
function SpecificRectangleProto(){}
SpecificRectangleProto.prototype = Rectangle.prototype;
SpecificRectangle.prototype = new SpecificRectangleProto();
var specrec = new SpecificRectangle(7,8,45);
alert(specrec.area);
I suggest to extract extend method from some framework. For example ExtJS. With such method you can extend class like this:
SpecificRectangle = extend(Rectangle, {
constructor: function(w,h,angle){
SpecificRectangle.superclass.constructor.call(this,w,h);
}
});
Upvotes: 1
Reputation: 30666
Honestly i don't know the exact reason but you need to set the prototype outside the constructor function:
function SpecificRectangle(w, h, angle) {
Rectangle.call(this,w,h);
}
SpecificRectangle.prototype = new Rectangle();
SpecificRectangle.prototype.constructor = SpecificRectangle; // Otherwise instances of SpecificRectangle would have a constructor of Rectangle
Working example here.
Edit following the comment by @herby:
It seems indeed that the upper method could break the prototypal inheritance depending on how the super-class constructor is built (see this article).
A more robust solution is to use Object.create
(source - thanks herby)
// in case Object.create does not exist
if (typeof Object.create !== 'function') {
Object.create = function(o) {
var F = function() {};
F.prototype = o;
return new F();
};
}
function Rectangle(w, h) {
this.width = w;
this.height = h;
}
Rectangle.prototype.area = function() {
return this.width * this.height
}
function SpecificRectangle(w, h, angle) {
Rectangle.call(this, w, h);
}
SpecificRectangle.prototype = Object.create(Rectangle.prototype);
SpecificRectangle.prototype.constructor = SpecificRectangle;
var r = new SpecificRectangle(100, 50, 30);
alert(r.area());
Updated example on jsfiddle
Upvotes: 3