Reactgular
Reactgular

Reputation: 54771

What's the difference between a function constructor and prototype constructor?

I would like to know what the difference between this

 MyClass = function() {};
 MyClass.prototype.Foo = function();

and this

 MyClass = {};
 MyClass.prototype.constructor = function() {};
 MyClass.prototype.Foo = function();

when it comes to declaring the constructor function for a prototype in JavaScript.

What is the advantage in using prototype.constructor over a regular function?

Upvotes: 2

Views: 875

Answers (2)

Aadit M Shah
Aadit M Shah

Reputation: 74204

Take a look at the following image, taken from the following answer:

When you create a new function, JavaScript automatically creates a new object (the prototype) as well:

  1. JavaScript sets the prototype property of the constructor function to the prototype object.
  2. JavaScript sets the constructor property of the prototype object to the constructor function.

Hence when you do this:

function Foo() {}

JavaScript actually does:

function Foo() {}
Foo.prototype = { constructor: Foo };

Why does JavaScript do this? Consider what happens when you create an instance of Foo:

var foo = new Foo;

When you create an instance of Foo using the new keyword, JavaScript actually creates an instance of Foo.prototype and not Foo. This means that foo inherits properties from Foo.prototype and not Foo. To make this point clear:

function Foo() {}

Foo.bar = true;

Foo.prototype.baz = true;

var foo = new Foo;

console.log(foo.bar); // undefined

console.log(foo.baz); // true

Now the advantage of having a constructor property on the prototype is that when you create an instance of Foo, the instance inherits the constructor property from the prototype. Hence you can use it to find out the type of an object:

function Foo() {}
function Bar() {}

function test(obj) {
    switch (obj.constructor) {
    case Foo: console.log("It's a Foo."); break;
    case Bar: console.log("It's a Bar."); break;
    default:  console.log("It's something else.");
    }
}

test(new Foo);
test(new Bar);
test(new Object);

Beside that there's nothing really special about the constructor property of the prototype. It's just an ordinary property. In the words of Tyler Durden: https://www.youtube.com/watch?v=4X2AvfSTi6Q

Since it is an ordinary property you can decide not to have a constructor property at all:

function Foo() {}
Foo.prototype = {}; // no constructor property

You can decide to make it point to some other function:

function Foo() {}
function Bar() {}
Foo.prototype.constructor = Bar;

You can decide to make it point to something other than a function:

function Foo() {}
Foo.prototype.constructor = "I am not a function.";

However, the point is that it's just another prototype property. In fact, we could use this to our advantage to create cleaner code. For example, this is how we normally create "classes" in JavaScript.

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

MyClass.prototype.sum = function () {
    return this.a + this.b;
};

MyClass.prototype.diff = function () {
    return this.a - this.b;
};

It's not very clean. Notice however that all three functions MyClass, sum and diff are prototype functions: constructor, sum and diff respectively. A prototype is just an object, and object literals in JavaScript provide a good form of encapsulation. We can use this to our advantage to write cleaner code:

function defclass(prototype) {
    var constructor = prototype.constructor;
    constructor.prototype = prototype;
    return constructor;
}

var MyClass = defclass({
    constructor: function (a, b) {
        this.a = a;
        this.b = b;
    },
    sum: function () {
        return this.a + this.b;
    },
    diff: function () {
        return this.a - this.b;
    }
});

That's much cleaner. In addition it shows us that the constructor property is just an ordinary prototype property. Hope that answers your question.

Upvotes: 8

uncle lee
uncle lee

Reputation: 31

MyClass.prototype.Foo = function(); this code add a static function for class MyClass, which means its instances can accsee the Foo function via dot operator. when we do new MyClass , first , we create a blank object like {}, and then we invoke the constructor on the object(MyClass.prototype.constructor.apply(obj, args)), at last, we set the prototype of the MyClass to the prototype of the object and return the object. So, when you write "MyClass.prototype.constructor = function() {}", the second step above will do nothing.

Upvotes: 0

Related Questions