Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Problems with changing constructor's prototype

Tags:

javascript

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. :)

like image 412
opportunato Avatar asked Aug 27 '26 23:08

opportunato


2 Answers

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?

The 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.

Why is it not working as you expected

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:

  1. Look at it's own properties and find no constructor
  2. Keep looking up to t.__proto__, which is Triangle.prototype. You have set it to shape which doesn't contain the constructor property.
  3. Continue looking up along the prototype chain - 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.
like image 147
steveyang Avatar answered Aug 29 '26 13:08

steveyang


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.

like image 27
Pointy Avatar answered Aug 29 '26 12:08

Pointy



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!