Inheritance

  1. Every object has a __proto__ property whose value is its parent object.

     var foo = {};
     foo.__proto__;  // Object { ... }
     foo.prototype;  // undefined
    
     var proto = foo.__proto__;
     typeof proto;               // "object"
     typeof Object;              // "function"
    
     proto === Object;           // false - object ≠ function
    
     foo   instanceof Object;    // true
     proto instanceof Object;    // false ?
    

    NOTE: Object is a constructor function. proto is different—it is an instance of Object(), not Object itself.



  2. The ancestral links between prototypes and their children is called the prototype chain.

    Human example:
     Grandparent
          \
         Parent
            \
           Child
    
    JavaScript example:
     Object
        \
       String
          \
        myString
    



  3. When an object's property is referenced, an property lookup takes place. During this process, JavaScript looks at all the object's own properties, and if the property is found, it is returned. However, if the property cannot be found, JavaScript will go to the object's prototype (or parent) and look there. If the property still cannot be found, JavaScript will look at the prototype's parent, and so on. JavaScript will continue this search until it reaches the end of the prototype chain, and if the property cannot be found by the end of the lookup, JavaScript will return the value undefined.


    Fun with __proto__


  4. foo's constructor property (foo.constructor) is not foo's own property. It is the property of foo's parent, Object (foo.__proto__).

     var foo = {};
     foo.constructor === foo.__proto__.constructor;  // true
    

    NOTE: An identifier resolution takes place when calling foo.constructor and foo.__proto__.constructor. Both expressions find the same constructor property within the prototype chain, and it happens to be the constructor property of foo's parent.



  5. foo's "grandparent" is null, and therefore, does not have a constructor.

     var foo = {};
     foo.constructor === foo.__proto__.__proto__.constructor;  // [1] error
    
     /*  Footnotes:
         [1] Uncaught TypeError: Cannot read property 'constructor' of null
     */
    

    Recall that foo's __proto__ is Object, and Object's __proto__ is null. This is why we get an error when trying to access the contructor property of Object's prototype.

    Here is the prototype chain for foo.

     var foo = {};
    
     foo.__proto__;                      // Object { ... }
     foo.__proto__.__proto__;            // null
     foo.__proto__.__proto__.__proto__;  // error - null does not have a __proto__ property
    

    The chain would look something like:

     null        // foo.__proto__.__proto__
       \
      Object     // foo.__proto__
         \
         foo     // foo
    



  6. Here is a similar example using a String object.

     var str = new String();
    
     str.constructor === str.__proto__.constructor;              // [1] true
     str.constructor === str.__proto__.__proto__.constructor;    // [2] false
    

    [1] shows that str's constructor property is not its own property, but is the property of its parent, String. Unlike previous example, no error is thrown at [2] since str's grandparent has a constructor property. Notice, however, that the constructor property of str's grandparent is different from that of str's parent.

    Consider the following:
     var foo = {},
         str = new String();
    
     foo.__proto__.constructor === str.__proto__.__proto__.constructor;  // true
    

    The expression above shows that the constructor property of foo's parent is the same constructor property of str's grandparent. This is because Object is both the parent of foo and the grandparent of str.

     foo.__proto__;              // Object { ... }
     str.__proto__.__proto__;    // Object { ... }
    
     foo.__proto__ === str.__proto__.__proto__;  // true
    

    Here is the prototype chain for a String object.

     var str = new String();
    
     str.__proto__;                      // String { ... }
     str.__proto__.__proto__;            // Object { ... }
     str.__proto__.__proto__.__proto__;  // null
    

    The chain would look something like:

     null            // str.__proto__.__proto__.__proto__
       \
      Object         // str.__proto__.__proto__
         \
        String       // str.__proto__
           \
           str       // str
    

results matching ""

    No results matching ""