4. prototype, __proto__ and inheritance in JavaScript
In the last post we mentioned a behavior of objects created when the new
keyword is used on a constructor function, i.e. JavaScript adds a property called as __proto__
which points to the prototype
property of the constructor function.
Note: Before EcmaScript 2015 or ES6 there was no official way to access an object's internal prototype
property. The formation of links for the purpose of inheritance was done using an internal property called [[prototype]]
. It is modern browsers and JavaScript engines who provide the __proto__
property to enable pointing to the constructor function's prototype
object.
Now let's see some code that reveals what happens under the hood. Let's define a constructor function(or also called as function constructor) and see whether really it has a property called prototype
function MyPseudoClass(){
this.myProperty = "Hello World!"
}
console.log(MyPseudoClass.prototype);//Output MyPseudoClass {}
Yes it does and its an object. Now let's create a new object using this function constructor and check its __proto__
property.
var myPseudoClassObject = new MyPseudoClass();
console.log(myPseudoClassObject.myProperty);//Output "Hello World!"
console.log(myPseudoClassObject.__proto__);//Output MyPseudoClass {}
Yes __proto__
and it also points to an object.
Are MyPseudoClass.prototype
and myPseudoClassObject.__proto__
pointing to the same object? We can easily check this using the below equality comparison because in JavaScript equality comparison of objects actually checks where these properties are pointing to in the memory.
console.log(MyPseudoClass.prototype===myPseudoClassObject.__proto__);//true
Yes they are the same!
Now does the newly created object have a prototype property by any chance?
console.log(myPseudoClassObject.prototype);//undefined
No it does not! As per JavaScript its not a constructor function and so it does not have its own prototype. Can we add one explicitly?
myPseudoClassObject.prototype = {
"language": "javascript"
};
console.log(myPseudoClassObject.prototype);//{ language: 'javascript' }
Yes we can and it remains as a property of myPseudoClassObject
only.
In a previous post I mentioned about another built-in object, the Function
object, which acts as the parent of any constructor function we create. So based on what we have learnt about the prototype
and __proto__
relation, the __proto__
of any constructor function should be pointing to the prototype
property of the built-in Function
object. Let's check if this is true:
console.log(MyPseudoClass.__proto__=== Function.prototype);//true
console.log(MyPseudoClass.__proto__);//[Function]
Yes it does! Now that we are aware of the relation of prototype
and __proto__
objects let us see what the internal structure of the prototype
object.
The prototype object
The prototype
object contains 2 properties of interest for us right now:
constructor
__proto__
The constructor
is nothing but a reference to the very object to which this prototype
belongs.
And the __proto__
points to either any other constructor function's prototye
or to the prototype
of the built-in Object
constructor function.
So it can be better visualized as below:
And this is what gives rise to the concept of prototype-based inheritance when we start linking one constructor function's __proto__
object to the prototype
of another constructor function.
We shall explore the inheritance mechanism of JavaScript in the next post.
References:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/constructor
https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Objects/Object_prototypes