Search code examples
javascriptinheritanceprototype-programming

How does assigning a base instance to the `.prototype` property differ from assigning the base prototype to `.prototype.__proto__`?


Given the following constructor,

Dog = function(name, age, ...){
    Animal.call(this, name, age, ...);
    // And some other stuff that dogs do
}

I use the following line of code to copy my methods and properties across from the Animal class,

Dog.prototype = new Animal();

Could you enlighten me as to how that differs from

Dog.prototype.__proto__ = Animal.prototype;

since they seem to have the same effect.


Solution

  • __proto__ is a non-standard extension to JavaScript (common in various interpreters, but non-standard) that gives you direct access to the prototype behind an object. The prototype property of function objects is the object that will be assigned as the prototype behind an object created by calling the function via new. So when you assign to prototype.__proto__, you're assigning to the prototype behind the object that will be set as the prototype on new objects created by the function.

    Since the way the prototype chain works is that properties on a prototype show up as inherited properties on an object (and this continues in a chain), if you assign to Dog.prototype.__proto__, the objects created by Dog will have access to those properties indirectly through the chain:

    +-----------------+      +----------------+      +-------------------------+
    | instance of Dog |----->| Dog.prototype  |----->| Dog.prototype.__proto__ |
    |                 |      |                |      | `foo` property          |
    |                 |      |                |      | `bar` property          |
    +-----------------+      +----------------+      +-------------------------+

    When you assign directly to Dog.prototype, the instances have a more direct reference:

    +-----------------+      +----------------+
    | instance of Dog |----->| Dog.prototype  |
    |                 |      | `foo` property |
    |                 |      | `bar` property |
    +-----------------+      +----------------+

    (Note that the above is slightly misleading by referring to Dog.prototype like that. Instances of Dog will get a direct reference to the object on Dog.prototype as of when new Dog is called; if you assign a completely different object to Dog.prototype later, instances that already exist will have the old prototype and new instances will get the new one. But that's a side-point.)