'How to properly set prototype?

I'm practicing an exercise in a book called Object-Oriented JavaScript.

The exercise in chapter 5 contains the following 4 questions:

  1. Create an object called shape that has the type property and a getType() method.
  2. Define a Triangle() constructor function whose prototype is shape. Objects created with Triangle() should have three own properties—a, b, and c, representing the lengths of the sides of a triangle.
  3. Add a new method to the prototype called getPerimeter().
  4. Test your implementation with the following code:

.

  var t = new Triangle(1, 2, 3);
  t.constructor === Triangle;  // true
  shape.isPrototypeOf(t);      // true
  t.getPerimeter();            // 6
  t.getType();                 // "triangle"

And this is my solution for the above questions:

var shape = {
    type: 'triangle',
    getType: function() {
        return this.type;
    }
};

function Triangle(a, b, c) {
    this.a = a;
    this.b = b;
    this.c = c;
}

Triangle.prototype = shape;  // Maybe something goes wrong here

Triangle.prototype.getPerimeter = function() {
    return this.a + this.b + this.c;
}

// ======================================================
var t = new Triangle(1, 2, 3);              
console.log(t.constructor === Triangle);  // false
console.log(shape.isPrototypeOf(t));      // true
console.log(t.getPerimeter());            // 6
console.log(t.getType());                 // triangle

Why does console.log(t.constructor === Triangle); output false as the result?

I've tried removing console.log(t.constructor === Triangle);, which makes t.constructor === Triangle equals true, but results in TypeError: t.getType is not a function error.

How can I make my execution results the same as the answers provided by this book?



Solution 1:[1]

Adding

Triangle.prototype.constructor = Triangle;

after

Triangle.prototype = shape;

solves my problem.

In chapter 6 page 173, the book says

Overwriting the prototype has side effects on the constructor property. Therefore, it's a good idea to reset the constructor after inheriting

Solution 2:[2]

Shape = {
  type: 'Shape',
  getType: function (){ return this.type;}
}

function Triangle( a, b, c){
    this.a = a;
    this.b = b;
    this.c = c;
    this.type = 'Triangle';
}

Triangle.prototype = Shape; 

Triangle.prototype.constructor = Triangle;

Triangle.prototype.getPerimeter = function (){
  console.log('Get Perimeter');
  return this.a + this.b + this.c;
  
}

var t = new Triangle(1,2,3);
console.log(t.constructor === Triangle);
console.log(Shape.isPrototypeOf(t));      
console.log(t.getPerimeter());            
console.log(t.getType()); 

Assign Shap object to Triangle.prototype and then overwrite constructor with Triangle will solve the problem.

Solution 3:[3]

function Shape() {
  type = "Shape";
 
}

Shape.prototype.getType = function() {
    return "Mi tipo es " + this.type;
  }

function Triangle(a, b, c) {
  Shape.call(this)
  this.a = a;
  this.b = b;
  this.c = c;
  this.type = "Triangle";
}

Triangle.prototype = Object.create(Shape.prototype);

Triangle.prototype.constructor = Triangle;

Triangle.prototype.getPerimeter = function() {
  return this.a + this.b + this.c;
}

var t = new Triangle(1, 2, 3);
console.log(t instanceof Triangle);
console.log(Shape.prototype.isPrototypeOf(t));
t.getPerimeter();
t.getType();

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 Senthil
Solution 3 Cristina MurguĂ­a