Reputation: 622
I'm trying to fully grasp the MDN documentation on Object.create but I'm left with a few questions that I haven't able able to crack.
Here is the example code MDN provides.
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();
One line I don't understand is Shape.call(this). I've looked up Object.call(this) but I couldn't find any documentation on it. What is this line of code doing?
Also, this line: Rectangle.prototype.constructor = Rectangle; What's the benefit of setting the constructor to Rectangle?
Finally, why would somebody implement use Object.create() over doing something like this:
Rectangle.prototype = new Shape()
Thanks!
Upvotes: 1
Views: 230
Reputation: 1309
When a function executes, the this
keyword points to the context - the object that called the function. The value of this
can be specified explicitly using the call() or apply() methods available on Function.prototype
. These functions take 2 arguments; the first is the object that will be the value of this
. When call() or apply() is used, the function is called using the argument object as its context (the function is called as a method of the object).
You also need to understand that when a function is used as a constructor, an object is created and the function is executed with the newly created object as its this
value. The newly created object also inherits the methods and properties of the constructor's prototype
property.
In your example, the Rectangle
constructor is trying to inherit the properties and method of the Shape
constructor.
function Rectangle() {
Shape.call(this);
}
When an instance of Rectangle
is created, the Shape
function is called with the newly created created instance of Rectangle
as its this value
. All the initialisation code inside the Shape
function are run on the newly created instance of Rectangle
.
Rectangle.prototype.constructor = Rectangle;
When a function is created, its prototype
property is automatically created. The prototype
property is an object that has a constructor
object that points back to the constructor function.
Object.create(proto) creates a new object whose prototype is the value of the argument supplied to it.
Rectangle.prototype = Object.create(Shape.prototype)
actually creates a new object that inherits the methods of Shape.prototype
and this object is assigned to Rectangle.prototype
. This overrides the original prototype
object automatically created. So, you need to explicitly define the constructor
property on the prototype
object using Rectangle.prototype.constructor = Rectangle
.
Upvotes: 1
Reputation: 707326
.call()
is a method on all Function objects. Shape
is a function so it has that method. Doc for .call()
here.
The code Shape.call(this)
says to call the Shape function and when you call it, make the this
pointer of that function point to the current value of this.
.
The purpose of that line of code is to call the base object's constructor.
Setting this:
Rectangle.prototype.constructor = Rectangle
is where an object stores the constructor that created it. It can be used by other code to either call the constructor of this class when trying to inherit from it, when trying to create another object of this type (without knowing exactly what type it is - assuming it doens't need any arguments) and various functions like that.
Object.create()
has a number of uses, but in your specific code example, it is used to create a new object that has the prototype of a specific object which is useful for inheritance. You can read more about it here.
Upvotes: 1
Reputation: 11725
Well, this is a object-oriented structure, so you should understand OOP before starting this. If you already do, let me explain what's going on:
The Rectangle "class" you're creating inherits the Shape "class".
So, the function Rectangle calls the Shape constructor, and then the Rectangle class will have the properties x and y initialized as 0, exactly as Shape class does.
The line "Rectangle.prototype.constructor = Rectangle;" is only declaring that the Rectangle class constructor is the function you've just declared above.
So, when you'll develop a new instance of Rectangle, you'll code:
var myRectangle = new Rectangle();
When you do that, it will call the Rectangle constructor, that will automatically call the Rectangle function, and this one will call the Shape constructor, and then your Rectangle object will have the properties x and y.
Try to debug it in some browser, and you'll see what I'm talking about.
In, C#, the equivalent code would be like:
public class Shape
{
public int X { get; set; }
public int Y { get; set; }
public Shape()
{
this.X = 0;
this.Y = 0;
}
public void Move(int x, int y)
{
this.X = x;
this.Y = y;
}
}
public class Rectangle : Shape // inherits the class Shape
{
public Rectangle() : base() // inherits the Rectangles constructor from Shape's constructor
{
}
}
Since Javascript is not a native object-oriented programming language, you need to do those "hacks" to create "classes" (all the time I'm using quotations, cause it's just a simulation of a class), and other hacks to inherits those classes etc.
Upvotes: 0