Reputation: 600
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
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