Recap
Lets start with person constructor function .
Person.prototype.calcAge = function () {
console.log(2021 - this.birthYear);
};
const Person = function (name, birthYear) {
this.name = name;
this.birthYear = birthYear;
};
This constructor function has a prototype property which is an object and inside the object we define the calcAge method and the Person.prototype also has a reference back to the Person which is the constructor property .
So Person.prototype.constructor will point back to Person itself .
Person.prototype is not the prototype of Person but it is the prototype of all the objects that is created using Person constructor function .
Speaking of object creation , Lets now analyze how objects are created using new keyword and constructor functions .
When we call a constructor function with new keyword things that are going to happen are -
- A new empty object { } is created .
- Function is called and in this call the this keyword will be set to the newly created object .
- Newly created object is linked ( __proto __ property ) to constructor function's prototype property .
- Function automatically returns the object.
Prototypal Inheritance
Lets understanding this with examples -
const jack = new Person('Jack', 1997);
jack.calcAge();
So here we are attempting to call the calcAge function on the jack object . However Javascript cannot find calcAge function directly in the jack object .
So what happens in this situation ??
Well if a property or a method is not found in a certain object . JavaScript will look into its prototype .
That's how the calcAge function can run correctly and return results and the behaviour we just describe is called Prototypal Inheritance .
So the jack object inherited the calcAge method from its prototype .
We can create as many Person objects as we like and all of them will inherit methods and properties from the prototype .
Now that fact that jack is connected to a prototype and abilities of looking up methods and propertiesin a prototype is what we call the prototype chain . So the jack object and its prototype forms a prototype chain but the prototype chain does not end here .
So here is a diagram of our object linked to its prototype via __proto__ property . But now lets remember that Person.prototype itself is an object and all objects in javascript have a prototype . Therefore Person.prototype itself must have a prototype and the prototype of Person.prototype is Object.prototype .
What is happening here ?
Well Person.prototype is just a simple object which means that it has been built by the built-in object constructor function and this is the function which is called behind the scenes whenever we create an object literal . The {} are just a shortcut to write new Object() .
These entire series of links between the objects is what is called Prototype Chain and Object.prototype is usually on top of the prototype chain which means its prototype is null . So its __proto__ property will simply point to null . It is very similar to scope chain but with prototype . So whenever JavaScript cannot find a certain property or method in a certain object its going to look up into the next prototype in the prototype chain .
Lets take an example to make it clear
jack.hasOwnProperty('firstName');
So here javascript is going to start by trying to find the called method on the object itself .
But ofcourse it can't find hasOwnProperty method in jack , so it will then look into its prototype which is Person.prototype . Now we didn't define any property named hasOwnProperty in Person.prototype also , so now javascript will look into Object.prototype and will find it there as hasOwnProperty is a method in Object.prototype .
Another one just to put a final nail in the coffin -
let arr = ['Sumit', 'Kumar'];
console.log(arr.__proto__.__proto__ === Object.prototype); //returns true
console.log(arr.__proto__.__proto__.__proto__); //return null
As we can see here whether we make an array , object or a function ,it actually down the prototype chain ends up being an object . If we create an Array it has prototype of Array.prototype and arr.__proto__.__proto__ is Object.prototype . So thats how the whole prototype chain works .