BezR
BezR

Reputation: 622

Javascript - understanding Object.create and Object.call(this)

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

Answers (3)

Akinkunle Allen
Akinkunle Allen

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

jfriend00
jfriend00

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

Buzinas
Buzinas

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

Related Questions