What are JavaScript Prototypes

avatar

Borislav Hadzhiev

Wed Feb 24 20213 min read

banner

Photo by Arun Clarke

Classes in JS #

ES2015 classes in JavaScript are just syntactic sugar, they don't really exist.

Classes were added in to make working with inheritance easier for programmers who were used to working with classes with the traditional OOP approach.

When we use an ES2015 class, it just uses the prototype system behind the scenes - even though we're using the class syntax we're still making use of prototypal inheritance.

Let's say we have the following class:

class Employee { constructor(title) { this.title = title; } work() { console.log(`The ${this.title} is working.`); } }

The real code that gets executed would be the following constructor function:

function Employee(title) { this.title = title; } Employee.prototype.work = function () { console.log(`The ${this.title} is working.`); };

We could then use this constructor function to initialize/use the different properties / methods we want an Employee to have:

const employee = new Employee('programmer'); employee.work();

Prototype property #

Inside of the constructor function we generally only associate the properties that we want an object to have, because the properties are mostly going to be unique between the different instances we create.

When it comes to methods - we place them on the prototype object - because the methods are most commonly the same between the instances, and it would be a waste of resources to duplicate those methods on every instance we create.

The solution used in the javascript language is to delegate the methods to the prototype object.

If you were to console.log the employee instance we created above you would see something like:

{ title: 'programmer', __proto__: { work: () => {}, ... } }

So we don't see the prototype property on the instance but we see a __proto__ property, that has access to the work method.

So how is __proto__ related to prototype?

  • __proto__ is the actual object that is used in the lookup chain to resolve methods. When we try to access a method like work directly on the instance employee - javascript first looks for the work method directly on the instance, when it doesn't find it - it works for the work method on the __proto__ object.

  • prototype is the object that is used to build __proto__ when we create an object with the new keyword. We assigned the work method on the prototype object, which is then used to build __proto__ which is used by the instances to look for methods, when they aren't found directly on the instance.

Another benefit of this delegation approach is that we can attach methods to the prototype object of the class after creating an instance, and still use that method on the instance - because javascript first is going to look for the method on the instance and when it doesn't find it - it will look on the prototype.

function Employee(title) { this.title = title; } Employee.prototype.work = function () { console.log(`The ${this.title} is working.`); }; const employee = new Employee('programmer'); Employee.prototype.drinkCoffee = function () { console.log(`The ${this.title} drinks coffee`); }; // works employee.drinkCoffee();

We can look back at a prototype and add, update or remove methods, and then they will be reflected between all the instances created from that constructor function.

Summary #

When we use classes in javascript - we still use the prototype system, every class translates to a constructor function with a prototype that stores all the different methods associated with the class.

Add me on LinkedIn

I'm a Web Developer with TypeScript, React.js, Node.js and AWS experience.

Let's connect on LinkedIn

Join my newsletter

I'll send you 1 email a week with links to all of the articles I've written that week

Buy Me A Coffee