javascriptconstructorprototypeprototype-chain

How function resolution in prototype chain will work for Object.prototype as constructor


I am referring to this web archive of an article originally on Helephant.com, to learn how Javascript resolves functions in the prototype chain when called on objects.

The article quotes,

If the object doesn’t have the method set directly on it, javascript then looks for a Constructor function that created the object. Javascript checks the constructor’s prototype property for the method.

In the following code, if you check rufus.constructor is the global Object() constructor, so will JS directly check the global Object() since rufus.constructor is Object() or as per the article quote above it will first look at the constructor and then find the prototype property and so on.. How will JS resolve the function (rufus.toString). I am quite confused with this.

  //PET CONSTRUCTOR
function Pet(name, species, hello)
 
  {   this.name = name;
      this.species = species;
      this.hello = hello; }
 
Pet.prototype = {
  sayHello : function(){
    alert(this.hello);
  }
}
 
//CAT CONSTRUCTOR
  function Cat(name, hello, breed, whiskerLength)
  {   this.name = name;
      this.hello = hello;
      this.breed = breed;
      this.whiskerLength = whiskerLength;}
  
Cat.prototype = new Pet();
var rufus = new Cat("rufus", "miaow", "Maine Coon", 7);

rufus.toString; 

Solution

  • If the object doesn’t have the method set directly on it, javascript then looks for a Constructor function that created the object. Javascript checks the constructor’s prototype property for the method.

    The wording is confusing. The JavaScript looks up the prototype chain through __proto__ and does not use constructor property. They mentioned Constructor because usually, that is how objects get their prototype - through Constructor.prototype property. But that is not always true. You can set the prototype like this:

    var rufus2 = Object.create(new Pet());
    Object.getPrototypeOf(rufus) === Object.getPrototypeOf(rufus2); // true
    

    Regarding how the toString method is resolved:

                        rufus.hasOwnProperty('toString'); // false -> go up
    (new Pet())         rufus.__proto__.hasOwnProperty('toString'); // false -> go up 
    ({sayHello :...})   rufus.__proto__.__proto__.hasOwnProperty('toString'); // false -> go up 
    (Object.prototype)  rufus.__proto__.__proto__.__proto__.hasOwnProperty('toString'); // true