Refactoring to preserve Liskov's Substitution Principle.
Note: Due "super" is a reserved word, "soper" is its replacement.
/* IShape -- abstract class */ function IShape(obj) { if(obj.area && obj.perimeter) return obj; else return undefined; }; /* Circle constructor */ function circle(radius) { return IShape( { "area": function() { return Math.PI * radius * radius; }, "perimeter": function() { return 2 * Math.PI * radius; } }); }; /* Rectangle constructor */ function rectangle(length, width) { return IShape( { "area": function() { return length * width; }, "perimeter": function() { return (2 * length) + (2 * width); } }); }; /* Triangle constructor */ function triangle(base, height) { return IShape( { "area": function() { return base * height; }, "perimeter": function() { return undefined; } }); }; /* Square -- child class -- constructor */ function square(side) { return IShape( { "soper": rectangle(side, side), "area": function() { return this.soper.area(); }, "perimeter": function() { return this.soper.perimeter(side, side); } }); }; /* Shapes factory */ function shapesFactory(shapeId) { switch (shapeId.toLowerCase()) { case "circle": return circle; case "rectangle": return rectangle; case "triangle": return triangle; case "square": return square; default: return undefined; } }; // TESTS var shape1 = shapesFactory("circle")(1); console.log("Circle(radius=1)."+ " Area: " + shape1.area() + " Perimeter: " + shape1.perimeter()); // output: // Circle(radius=1). Area: 3.141592653589793 Perimeter: 6.283185307179586 var shape2 = shapesFactory("rectangle")(2,3); console.log("Rectangle(length=2, width=3)."+ " Area: " + shape2.area() + " Perimeter: " + shape2.perimeter()); // output: // Rectangle(length=2, width=3). Area: 6 Perimeter: 10 var shape3 = shapesFactory("triangle")(2,3); console.log("Triangle(base=2, height=3)."+ " Area: " + shape3.area() + " Perimeter: " + shape3.perimeter()); // output: // Triangle(base=2, height=3). Area: 6 Perimeter: undefined var shape4 = shapesFactory("square")(1); console.log("Square(radius=1)."+ " Area: " + shape4.area() + " Perimeter: " + shape4.perimeter()); // output: // Square(radius=1). Area: 1 Perimeter: 4