I'm currently going through Stoyan Stefanov's book "Object-oriented JavaScript" and I've stumbled on an interesting problem. Here's the code:
var shape = {
type: 'shape',
getType: function() {
return this.type;
}
};
function Triangle(a, b, c) {
this.a = a;
this.b = b;
this.c = c;
this.type = 'triangle';
}
Triangle.prototype = shape; // changing the prototype object
Triangle.prototype.getPerimeter = function() {
return this.a + this.b + this.c;
}
var t = new Triangle(1, 2, 3);
t.constructor; // logs Object() instead of Triangle(a, b, c)
As you can see, here is a simple example of the constructor inhereting some properties from the prototype object. But the constructor property of object t points to the Object() object instead of Triangle(a, b, c), as it should have. If I comment the line with the prototype change, though, everything works fine. What's my problem? (Reread the whole prototype chapter in Object-oriented Javascript and JavaScript Patterns, couldn't find an answer). P.S. Sorry for my bad English, trying to practice it. :)
I will explain your code in two parts. Firstly, what is the constructor property actually? Secondly, why doesn't it return Objects in your code?
constructor property and Stoyan's mistake:In Stoyan Stefanov's book, p150, he states:
prototype is a property that gets created as soon as you define the function. Its initial value is an empty object.
It is wrong. According to the JavaScript Definitive Guide Section 9.2
The initial value of the prototype property is an object with a single property. This property is named constructor and refers back to the constructor function with which the prototype is associated.
You can test it with Triangle.prototype.constructor. It has been set when the function is defined.
Conclusion 1: the constructor is in fact the property of Constructor.prototype. In your case, it is Triangle.prototype.constructor.
All the instances of Triangle could access this property through the prototype chain. But these objects themselves don't have the constructor property. The following code proves it:
function Triangle(a, b, c) {
this.a = a;
this.b = b;
this.c = c;
this.type = 'triangle';
}
var t = new Triangle(1, 2, 3);
t.hasOwnProperty('constructor');
>>false
t.__proto__.hasOwnProperty('constructor');
>>true
Conclusion 2: when you access the constructor property of an instance, you get them from the prototype chain.
You set Triangle.prototype to shape which doesn't contain the originalconstructor property.
Thus, this time, when you query t.constructor, it will resolve it in the following process:
constructort.__proto__, which is Triangle.prototype. You have set it to shape which doesn't contain the constructor property.t.__proto__.__proto__. It is Triangle.prototype.__proto__, and it is resolved as Object.prototype. Object.prototype has the constructor property and it refers to Object.The "constructor" property, oddly enough, does not refer to the constructor of that object. Rather, it refers to the constructor of the object's prototype.
Here is the relevant doc page from Mozilla.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With