user2913184
user2913184

Reputation: 600

JavaScript prototype and constructor

I have following piece of code for the purpose of learning JavaScript.

function Pizza(type, slices) {
    this.type = type;
    this.slices = slices;
}


Pizza.prototype.divvyUp = function () {
    alert("The " + this.type + " pizza has been divvied up!");
};

var sausagePizza = new Pizza("sausage", 8);


sausagePizza.constructor.prototype.divvyUp();
sausagePizza.divvyUp();
if (sausagePizza.constructor.prototype.divvyUp === sausagePizza.divvyUp)
{
    alert("yes they are equal");
}

The thing is that when these two lines of code are executed:

sausagePizza.constructor.prototype.divvyUp();
sausagePizza.divvyUp();

Though the if statement next to them ratifies that they are equal as far their types and values are concerned. But the First line gives me a result which reads like this "The undefined pizza has been divvied up" and the second line turns out to be giving me a little different result which reads as "The sausage pizza has been divvied up". I'm super confused that why can't first line among these two read this.type variable value and throws an undefined from the alert message inside divvyUp() function when they are equal according to the if statement.

Upvotes: 0

Views: 235

Answers (1)

Hath995
Hath995

Reputation: 1300

The differences between the two concerns how "this" is bound within the function calls.

The object on the left of the . in front of the function call is the object which "this" is bound to.

sausagePizza.constructor.prototype.divvyUp();
//sausagePizza.constructor.prototype is left of the .divvyUp()
//so it is bound to this. However, the prototype object does not have
//a type property so it this.type returns undefined

However, for the case of sausagePizza, the constructor did create those properties.

sausagePizza.divvyUp()
//here sausage pizza is to left of .dizzyUp() and "this" is bound to it.

Edit: To understand prototypes in Javascript it might help to have everything completely spelled out. First Functions are objects, which means that they have properties. Every function is created with some basic properties. One of these is the prototype, which starts out as an empty object.

function Pizza(type, slices) {
  this.type = type;
  this.slices = slices;
}
console.log(Pizza.prototype) // prints {} an empty object

Pizza.prototype.divvyUp = function () {
  alert("The " + this.type + " pizza has been divvied up!");
};
console.log(Pizza.prototype) // prints {divvyUp: [Function]}

Now when we use the new operator in front of a function it creates a new empty object, sets the object __proto__ and constructor properties, and then runs the function with "this" bound as the new object.

var sausagePizza = new Pizza("sausage", 8);
console.log(sausagePizza) // {type: "sausage", slices: 8}
//Objects in javascript can have hidden properties. 
//If we unhide the relevant ones for this example
//sausagePizza really looks like this.

{
   constructor: Pizza, //the function
   __proto__: Pizza.prototype, //the object on the function
   type: "sausage",
   slices: 8
}

So the . operator actually works by looking into the object on the left for the key on the right (e.g. . ). If it does not find the key it is looking for in the properties object on the left, then it looks into the __proto__ of the object for the key. So when you do

sausagePizza.divvyUp()
//Javascript first looks into sausagePizza for divvyUp.
//It does not find it.
//then it looks for divvyUp in sausagePizza.__proto__
//it find divvyUp there and then () calls the function
//if javascript had not found divvyUp in sausagePizza.__proto__ then it would have
//looked into sausagePizza.__proto__.__proto__ if it existed, and so on

Upvotes: 2

Related Questions