Reputation: 7547
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
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.prototype
– Rectangle
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
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