Blake
Blake

Reputation: 7547

Why we need to define constructors in JavaScript

I am reading this piece of code

// Shape - superclass
function Shape() {
  this.x = 0;
  this.y = 0;
}

// superclass method
Shape.prototype.move = function(x, y) {
  this.x += x;
  this.y += y;
  console.info('Shape moved.');
};

// Rectangle - subclass
function Rectangle() {
  Shape.call(this); // call super constructor.
}

// subclass extends superclass
Rectangle.prototype = Object.create(Shape.prototype);
Rectangle.prototype.constructor = Rectangle;

var rect = new Rectangle();

rect instanceof Rectangle; // true
rect instanceof Shape; // true

rect.move(1, 1); // Outputs, 'Shape moved.'

I got really confused by this snippet

Rectangle.prototype = Object.create(Shape.prototype);
Rectangle.prototype.constructor = Rectangle;

Why don't we use Rectangle.prototype = Shape.prototype, anything special that Object.create() does? and what if Rectangle.prototype.constructor = Rectangle; is not called?

Upvotes: 1

Views: 180

Answers (2)

David Aurelio
David Aurelio

Reputation: 504

If you’d just set Rectangle.prototype to Shape.prototype, then both Rectangle and Shape would share the same object as prototype. That would mean, that everything you add to Rectangle.prototype would also be available on Shape.prototypeRectangle would no longer inherit from Shape.

Object.create(parent) creates a child object that inherits from the parent object passed in. This way, all properties of the parent are also available to the child, while properties on the child don’t affect the parent.

To answer your question (“Why we need to define constructors in JavaScript?”) – we don’t need to. You could also just use plain objects:

// Shape - superclass
function Shape() {
  return {
    x: 0, 
    y: 0,
    // superclass method
    move: function(x, y) {
      this.x += x;
      this.y += y;
      console.info('Shape moved.');
    }
  };
}

// Rectangle - subclass
function Rectangle() {
  var rectangle = Shape();
  // rectangle-specific things could be added here
  return rectangle;
}

var rect = Rectangle();

rect instanceof Rectangle; // false, instanceof does not work here
rect instanceof Shape; // false

rect.move(1, 1); // Outputs, 'Shape moved.'

Upvotes: 0

plalx
plalx

Reputation: 43718

If you do Rectangle.prototype = Shape.prototype then any modification that you will perform on Rectangle.prototoype will reflect on Shape.prototype because they are the same object.

To avoid this, we create a new object that has it's prototype link pointing to Shape.prototype using Object.create(Shape.prototype).

As for Rectangle.prototype.constructor = Rectangle;, it's to make sure that new Shape().constructor points to Rectangle, not Shape.

The native prototype of a function has a constructor property that points to that function.

e.g.

function Rectangle() {}

Rectangle.prototype.constructor === Rectangle; //true

Now, when we do Rectangle.prototype = ..., we break that reference and need to fix it afterwards.

Upvotes: 2

Related Questions