Question

Consider the following snippet:

function Dog(){this.tail = true;}
var benji = new Dog();
var rusty = new Dog();
Dog.prototype.say = function(){return 'Woof!';}
alert(benji.say()); // this alerts woof!
alert(rusty.say()); // this alerts woof!
alert(benji.constructor.prototype.constructor); // THIS ALERTS THE DOG FUNCTION
alert(typeof benji.constructor.prototype.tail) // THIS ALERTS UNDEFINED

Why does the benji.constructor.prototype.constructor alert the dog function? Shouldn't it be an Object() constructor?

Was it helpful?

Solution

It's simple:

+-----------------+       tail
|                 |-----------------> [true]
|      benji      |
|                 |
+-----------------+
         |
         | __proto__
         |
         v
+-----------------+    constructor    +-----------------+
|                 |------------------>|                 |
|  Dog.prototype  |                   |       Dog       |
|                 |<------------------|                 |
+-----------------+     prototype     +-----------------+
         |
         | __proto__
         |
         v
+-----------------+    constructor    +-----------------+
|                 |------------------>|                 |
| Object.prototype|                   |      Object     |
|                 |<------------------|                 |
+-----------------+     prototype     +-----------------+
  1. benji.constructor is Dog.
  2. benji.constructor.prototype is Dog.prototype.
  3. benji.constructor.prototype.constructor is Dog.
  4. benji.constructor.prototype.constructor.prototype is Dog.prototype.
  5. benji.constructor.prototype.constructor.prototype.constructor is Dog.

This goes on forever. Instead what you want is Object.getPrototypeOf:

  1. Object.getPrototypeOf(benji).constructor is Dog.
  2. Object.getPrototypeOf(Object.getPrototypeOf(benji)).constructor is Object.

Since Object.getPrototypeOf is iterated you could create a special function for it:

function getPrototypeOf(n, object) {
    if (n === 0) return object;
    else return getPrototypeOf(n - 1, Object.getPrototypeOf(object));
}

Now you can use it as follows:

getPrototypeOf(1, benji).constructor; // Dog
getPrototypeOf(2, benji).constructor; // Object

That's all folks.

OTHER TIPS

benji.constructor resolves to Dog. Note that benji doesn't actually have it's own constructor property: it inherits the constructor property from its prototype. benji.constructor really is Dog.prototype.constructor, just like benji.say is really Dog.prototype.say.

Thus, benji.constructor.prototype is actually Dog.prototype, which is the prototype where benji inherits prototypal properties from.

Finally, therefore, benji.constructor.prototype.constructor is really Dog.prototype.constructor, which is the same as benji.constructor.

By contrast, benji does have his own tail property. That is set directly on the instance when it is constructed, and it is not inherited from the prototype.

This is because the prototype of Dog doesn't contain the property. Instead, you are setting it for every new instance, inside the constructor function. To have tail in the prototype, you'd have to define it there:

Dog.prototype.tail = true;
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top