- Class-Based Language - It is a style of Object-Oriented Programming, a Class-Based Language uses Classes as models for the objects, inside the Class we have the properties and methods. All the objects in a Class-Based Language are instantiated based on Classes and the inheritance is created between Classes, each Class extends another Class.
As you understood the idea about Prototype-Based Language, we can take a look on the example below:
Look at this example, we have created an Empty Object called obj1, then we tried to display the name property, obviously, it returned undefined, because we do not have a name property in obj1. But, now look at the line 6, we have created a new Object with the name property and we kept it in the obj1's __proto__ property, however what is the __proto__ property?
Now, if we add the name property in obj1 like we did in the line 10, when we try to display it, it shows the obj1's name property and does not show obj1's prototype's name property. With this example, you understood how an inheritance works in a Prototype-Based Language.
To access the Function's Prototype we have the prototype property, when we create an Object from a Constructor Function, the Object's __proto__ has the same reference of the Constructor Function's Prototype, as we can see on the line 8. So, every change we make on the Person's Prototype will affect all the objects which were instantiated based on it.
Problems with prototype
When we are working with Prototype, we must be careful, especially when we are manipulating objects. As we already know, a Prototype-Based Language uses objects to create inheritance. Suppose we have a Constructor Function called Person that has a names array on its Prototype, if we instantiate two new objects (person1 and person2) based on Person and on the person1 we add a new element on the names array, then we will change the Prototype's array, to understand it better, let us see this example:
Look at the line 12, we are adding a new element to the names array, person1 does not have a names property, its Prototype has this property, though. But the person1's Prototype is shared between all Objects which were instantiated based on the Person, if we add the element on it, we are going to affect all instances, as we can see on the lines 14 and 15.
It is pretty simple to fix this problem, we just have to create a names array for each instance instead of creating it on the Person's Prototype. Then, when we change it, only the object's array will be changed, like this example:
It is the enough to fix our problem, This problem will happen every time we try to change an Object that is owned by the Object's Prototype, be careful when using Objects in the Prototype.
Prototype improves Memory Usage
Using prototype is a good way to improve the Memory Usage, let us suppose we have an Object which has a name property, we want to create a Getter Function to return the name property. It is easy, we can write something like the code below:
It is not wrong, but there is a Memory Usage Problem here. When we create a function inside the Constructor Function we are creating a new function for every instance of Person, we can see it on the line 12, we are comparing if person1.getName and person2.getName to see if they have the same reference, however they are different, so we have 2 instances of getName here.
If person1.getName and person2.getName do the same thing, why do not we just create a getName function in the Person's Prototype to keep only one instance of this function? We are able to do it just writing a code like this:
This code creates a getName Function inside Person's Prototype, now when we compare person1.getName and person2.getName they are equal. This is an example of how we can improve the Memory Usage with Prototype.
We are going to create two Sub Constructor Functions called Dog and Cat which will extend the Super Constructor Function called Animal. The Animal is going to have 2 properties (age and name), each property will have a Getter Function, let us write it:
Our Animal Function and its Sub Functions are done. Let us understand what was done here:
- Line 1 to 12 - We created the Animal Constructor Function with its properties (age and name) and Getter Functions.
- Line 14 to 19 - The Dog Constructor Function is created, with a call to Animal Constructor (Line 16) and setting an Animal Object as the Dog's Prototype.
- Line 22 to 27 - On these lines, we did the same as we did with the Dog Constructor Function, but with the Cat Constructor Function.
Now, we are going to use the instanceof operator to check if Dog and Cat are Animal's children. Basically, the instanceof operator checks if the right Constructor Function's prototype appears on the left object's Prototype Chain, returning true or false.
This tutorial finishes here, if you have any doubt or suggestions about what we discussed, feel free to contact us on this email, we will be happy to hear of you!
See you on the next tutorial!!