What on Earth are JavaScript Prototypes?
The often-overlooked concept of JavaScript!
Introduction
Prototypes in JavaScript are the mechanism to share standard functionalities between objects. Almost all objects in JavaScript are instances of Object
. A typical object inherits all the properties and methods from Object.prototype
.
In simple terms, a prototype is an object from where JavaScript objects inherit methods and properties from.
Sounds like Greek? Well, don't worry. Go on. I've got you covered.
What is a PROTOTYPE?
When a function is created in JavaScript, the JavaScript engine adds a prototype
property to it. This prototype
property is an object called a prototype object with a constructor
property by default. The constructor
property points back to the function on which the prototype
object is a property. We can access the function's prototype property using functionName.prototype
.
Take this function as an example,
As you can see in the below diagram, the Person constructor function has a prototype property that points to the Prototype object. And in return, the Prototype object has a constructor property that points back to the Person function.
Let's see this in action,
In the above screenshot, an object man
is created from the Person function with the new
keyword. You can clearly see a property __proto__
. This indeed is the prototype property mentioned in the diagram above. I have explained this __proto__
property further below. It is quite evident that the __proto__
property is pointing to the prototype object, and the prototype object is containing the constructor of the Person function. I hope it all makes sense now.
How does it work?
When you access a property in an object, something called "Prototype Chaining" takes place. This is what happens.
- The property is first sought on the object as an own property
- If the property isn't found on the object, its prototype is checked next
- If the property doesn't exist on the prototype, the prototype of the prototype is queried
- This querying of prototype and its prototype continues until the property is discovered or the end of the prototype chain is reached, at which instance an error is returned.
For example, let's take the man object. If I access the name
property of the man object, the JS engine checks whether it is the object's own property - which is in this case. Suppose the name
property is not present in the object's own property. Then the JS engine checks the object's prototype until the property is found. Else an error is returned.
DID YOU KNOW?
When you take a string such as "Jane Doe", you will be able to access and executes methods such as toLowerCase
, concat
, slice
because they are available in the String prototype object.
Now you must be understanding what the prototype in String.prototype.slice()
meant in the MDN Web Docs!!!
Screenshot of the MDN Web Docs
__proto__ vs prototype
__proto__
is the actual property that is looked up during the prototype chaining. It is kind of like a pointer to the prototype
object, which holds all the methods and properties.
When you use the new
keyword to create an object, __proto__
is built using a prototype
object. To be specific, the methods and properties are stored in the prototype
property on the object's constructor function, not in the object instance itself.
Take a look at this example,
I have added a new method to the prototype
object, not the object instance itself. This method is a simple toString()
, which returns the name and the job.
When you console.log(man.__proto__)
, which is the pointer to the prototype
object, this is what you will receive.
You can clearly see a function in the property toString
. This is what that gets called when I access man.toString()
.
Why should you use prototypes when working with objects and inheritance?
Refer to the previous example where I created a man and women object from the Person function constructor.
Instance 1
This is how it will look without the toString function I added to the prototype.
Instance 2
When I add the toString property to the prototype, this is how the structure will look.
Instance 3
Suppose I add the toString property to the Person function itself. This is how things would look like.
You can clearly see the difference between instance 2 and instance 3.
When you do not apply a prototype, every time you create an object instance, all the properties are associated with the instance of the object. This means that they will be pointing to a different memory location for each object instance.
Imagine creating 1000 similar objects with repetitive functions like the toString
I have used above. You can save lots of unnecessary memory usage by using prototypes. But keep in mind that you should know when to use this.
Conclusion
Prototypes are crucial in JS utilities and libraries. As I mentioned above, all objects in JS inherit the prototype object, which makes it a fundamental building block of JS.
I am aware that I am unable to fully explain this concept in this mere 5-minute piece. Hence I strongly advise you to follow the resources I have attached below.
I hope you got some idea about this mysterious prototype
. Happy learning!
Resources