Search code examples
javascriptobjectinheritanceconstructorprototype

Differences in inheritance of parent objects prototype


I found 3 ways to inherit the prototype of another Object-constructor:

Can I use all three? => They seem to work if I test the draw() method on a Rectangle instance...

Are there other ways of doing this?

function Shape(shapeName){
    this.shapeName = shapeName;
}
Shape.prototype.draw = function(){
    console.log('I am a '+this.shapeName+' and I am drawing myself');
}

function Rectangle(shapeName,l,b){
    Shape.apply(this,arguments);
    this.lengte = l;
    this.breadth = b;
}

// Possibility 1 ==> Rectangle.prototype = Object.create(Shape.prototype);
// Possibility 2 ==> Object.assign(Rectangle.prototype,Shape.prototype);
// Possibility 3 ==> Rectangle.prototype = Shape.prototype;

Solution

  • Can I use all three?

    Sort of, but I would strongly recommend using Possibility 1 (plus setting constructor on the result to Rectangle):

    function Shape(shapeName){
        this.shapeName = shapeName;
    }
    Shape.prototype.draw = function(){
        console.log('I am a '+this.shapeName+' and I am drawing myself');
    }
    
    function Rectangle(shapeName,l,b){
        Shape.apply(this,arguments);
        this.lengte = l;
        this.breadth = b;
    }
    
    Rectangle.prototype = Object.create(Shape.prototype);
    Rectangle.prototype.constructor = Rectangle;
    

    Why I wouldn't use Possibility 2: It copies everything over, which means subsequent modifications to Shape.prototype won't be inherited by Rectangle.prototype.

    Why I wouldn't use Possibility 3: It means you can't give Rectangle methods that Shape doesn't have (since adding to Rectangle.prototype is adding to Shape.prototype as they're the same object), and it falsely makes triangle instanceof Rectangle true if you also have Triangle created the same way and used triangle = new Triangle() to create triangle.


    Possibility 1 is also essentially what ES2015+ class syntax does when you do class Rectangle extends Shape { }. And in fact, what I would recommend using (potentially with a transpiler):

    class Shape {
        constructor(shapeName) {
            this.shapeName = shapeName;
        }
        draw() {
            console.log('I am a '+this.shapeName+' and I am drawing myself');
        }
    }
    
    class Rectangle extends Shape {
        constructor(shapeName, l, b){
            super(shapeName);
            this.lengte = l; // <=== Maybe you meant "length"?
            this.breadth = b;
        }
    }