0

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.

18
  • 2
    possible duplicate of How does JavaScript .prototype work? Commented May 31, 2015 at 22:47
  • 2
    possible duplicate of How does the "this" keyword work? Commented May 31, 2015 at 22:49
  • 1
    You have it backwards. Pizza.prototype is the prototype of sausagePizza. Yes, Pizza.prototype and sausagePizza.constructor.prototype are the same object (since sausagePizza.constructor points to Pizza). Commented May 31, 2015 at 23:28
  • 1
    Pizza is a constructor function, and like any other function (all functions are also objects) its prototype is Function.prototype. Constructor functions make all of this a little harder to learn, because Pizza.prototype doesn't actually refer to the prototype of the Pizza constructor function, but rather is only used by JS when setting the prototype of new instances of Pizza. Commented May 31, 2015 at 23:42
  • 1
    This example which doesn't use constructor functions at all might help clarify things: jsfiddle.net/uutyb82d. I don't write my own code that way but it might be helpful for illustrative purposes. I used getter and setter functions which don't work in IE8 and below...the reason I used them was so I could show a way of safely putting data properties on the prototype. Ordinarily I avoid that because it can lead to unintentionally shared prototype properties. See bennadel.com/blog/… Commented May 31, 2015 at 23:44

1 Answer 1

2

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
Sign up to request clarification or add additional context in comments.

2 Comments

And BTW, calling sausagePizza.constructor.prototype.divvyUp() is not something you should have a need for in practice...
I know, but just wanna understand the prototype concept clearly.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.