Voiced by Amazon Polly |
Introduction
JavaScript is a prototype-based language. Prototypes are a way by which objects in JavaScript communicate with each other and can share their properties and methods. This can prove very useful to minimize code and logic repetition as the main common logic or property can be written separately from the main logic. Still, we use the entire application without breaking any underlying functionalities.
Pioneers in Cloud Consulting & Migration Services
- Reduced infrastructural costs
- Accelerated application deployment
Prototype in Javascript
Regarding prototypal inheritance JavaScript works differently from other object-oriented programming languages. Here everything works based on objects and objects only. In JavaScript objects, apart from our usual methods and properties, we also have another object called a prototype.
This prototype object is used for establishing connections between different objects and using those properties. The interesting part is that the prototype object itself has its prototype, which continues until we react to the null value. The null value at the end does not have its prototype and is the endpoint.
Through this inheritance, the objects can look up its prototype for values and methods it does not contain or is not defined.
Ways of Creating Prototypes in JavaScript
1) Using the function.
We can first use prototypes in JavaScript by using function constructors. The User function puts all the fields common to all the objects. In the function, this refers to the instance created by the function constructor. In this instance, the value of ‘this’ refers to the Ajax and Roach instance.
The common logic to calculate age, i.e., ‘calculateAge’, is not defined in each object. Rather we have written the method logic inside the prototype of the User function.
When we create an instance from the function constructor using a new keyword, the instance ‘Ajax’ and ‘Roach’, all the content of the function prototype gets stored in this ‘__proto__’ keyword. So, in a way, ‘proto’ links to the prototype. If we check, both will be the same.
After running the code below, you can see in the terminal that we get the current ages of our users by using the method defined in the prototype and passing the current year as the parameter.
So, when the function is called, JavaScript cannot find the method defined in the instances created by the constructor function, and hence it checks the __proto__ if there is something called ‘calculateAge’. In this case, the code finds the function in the prototype and hence returns the users’ ages without breaking the code. If it does not find it, the code would keep looking up the prototype chain to find the method unit until it reaches null, which is the endpoint.
This prototype approach follows ‘DRY’ and gets work done by separating the logic from the main code. But this is an old method of working with prototypes.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
let log = console.log; Function User(name,yearofbirth,mail){ this.name = name; this.yearofbirth = yearofbirth; this.mail = mail; }; User.prototype.calculateAge = function(currentYear){ return currentYear – this.yearofbirth; }; let Ajax = new User(‘Ajax’,1999,’ajax@mail.com’); let Roach = new User(‘Roach’,1998,’roach@mail.com’); Let ajaxage = Ajax.calculateAge(2023); let roachage = Roach.calculateAge(2023); log({Ajax:ajaxage,Roach:roachage}) |
From the code below, it’s evident that both instances do not have any method defined within themselves. Rather they take advantage of the prototype to use the function. Also, we can see that __proto__ and prototype hold the same value and return true.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
let log = console.log; function User(name,yearofbirth,mail){ this.name = name; this.yearofbirth = yearofbirth; this.mail = mail } User.prototype.calculateAge = function(currentYear) { Return currentYear – this.yearofbirth; } let Ajax = new User(‘Ajax’,1999,’ajax@mail.com’); let Roach = new User(‘Roach’,1998,’roach@mail.com’); let ajaxage = Ajax.calculateAge(2023); let roachage = Roach.calculateAge(2023); log(Ajax.hasOwnProperty(‘calculateAge’)); log(Ajax.__proto__.hasOwnProperty(‘calculateAge’)); log(Ajax.__proto__ === User.prototype) |
2) Object.create()
Object.create() creates a new object with an existing object as a prototype of the newly created object.
Here we pass the common object as a parameter to Object.create(). This links the new object __proto__ to the object passed. So, the new object can access the ‘calculateAge’ function to get the age of the instance.
Rest working is similar to the one discussed in the function approach for creating prototypes.
1 2 3 4 5 6 7 8 9 10 11 12 |
let common = { CalculateAge(currentYear){ Return currentYear – this.yearofbirth } } let Soap = Object.create(common); Soap.name = ‘Soap’; Soap.yearofbirth = 1998; Soap.mail = ‘soap@mail.com’; Log(Soap.calculateAge(2023)); Log(Soap.__proto__); |
3) Javascript Class
Class is the new way of working with prototypes and inheritance in Javascript. It was introduced as an ES6 feature. Classes in JS are built on prototypes but have some syntax and semantics that are unique to classes.
Classes can be considered as syntactic sugar over the prototype-based inheritance model. Here we have replaced the function method of creating instances with the constructor.
The constructor is used to initialize the instance properties, as shown below. While working with classes, we must make sure to spell constructor right and that it is initialized automatically when a new instance is created. Another important rule is that we cannot hoist classes, which work in strict mode.
The method ‘calculateAge’ is now common to all the instances created, and you can pass down parameters to it as normal functions. Javascript classes also make it easy to work with inheritance.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
class User{ constructor(name,yearofbirth,mail){ this.name = name; this.yearofbirth = yearofbirth; this.mail = mail; } calculateAge(currentYear){ return currentYear – this.yearofbirth; } } let Gaz = new User(‘Gaz’,1993,’gaz@mail.com’); Let Reznov = new User(‘Reznov’,1975,’reznov@mail.com’) Let age1 = Gaz.calculateAge(2023); Let age2 = Reznov.calculateAge(2023); Log({Gaz:age1,Reznov:age2}) |
Conclusion
In this blog, we explored some basic working with one of the most important features in JavaScript language and how to work with it.
Prototypes are a very powerful tool and are helpful in lots of ways. JavaScript also provides us with a prototype inheritance feature which adds to already powerful prototype features.
Making IT Networks Enterprise-ready – Cloud Management Services
- Accelerated cloud migration
- End-to-end view of the cloud environment
FAQs
1. Why use a prototype?
ANS: – Prototypes in JavaScript are a way of communicating among JavaScript objects. It helps us to separate common logic from the main code and, on top of that, has the feature of inheritance. Using and understanding prototypes is a crucial part of learning JavaScript language.
2. Do all objects have prototypes?
ANS: – Yes, all JavaScript objects have prototypes which in turn are objects themselves and may contain prototypes within themselves. This, in turn, leads to a functionality called prototype chain.
3. Examples of daily uses of prototypes.
ANS: – One very important usage of prototypes in JavaScript is creating polyfills for Array and String objects in JavaScript. Polyfills help write new JavaScript features for old browser versions without support for the latest features.
WRITTEN BY Rishav Mehta
Click to Comment