Search code examples
javascriptinheritancemethodscallprototype-programming

Child class can't call its parent's prototype method


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?


Solution

  • 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