A simplified overview of JavaScript prototypes and prototypical inheritance.

What are the two types of prototypes in JavaScript and what are they used for?

Eamon O'Callaghan
Launch School
7 min readJul 26, 2021

--

Macbook showing a code snippet on the screen.

To understand prototypes and inheritance in JavaScript, you will need to understand these five points:

  1. Objects can have properties.
  2. Objects inherit properties from their prototype.
  3. Functions are objects which can also have properties.
  4. Functions have a prototype property.
  5. A function’s prototype is NOT the same thing as an object’s prototype.

Let’s examine each of these points in more detail.

Disclaimer: The information in this article is information that I have learned from Launch School, MDN, and this excellent video by a Launch School student called Ryan Schaul. I am a student at Launch School and I wanted to write an article that presents the basic concepts of prototypes in an easy-to-understand manner. Code snippets are linked at the bottom of the article.

Objects properties

The first thing you need to know is that objects in JavaScript can have properties. For example, the object foo here has a property called bar:

A code snippet showing an object foo with a property called bar.

Its property can be accessed using dot notation as we see on line 5. On line 6 we verify that foo has a property called bar by calling the hasOwnProperty method.

Object prototypes and inheritance

Objects usually have many properties that you can’t see by simply logging the value of the object. This is because objects can inherit properties from their prototype. The object that another object inherits properties from is called its prototype.

If you need a mental model, you can think of how a child inherits characteristics from its parent. In this example, the parent would be considered the ‘prototype’ and the child the ‘object’.

An object’s prototype is a private property that each object has that references or points to its prototype (the object that it inherits from). According to the JavaScript documentation at ECMAScript, this internal property is called [[Prototype]].

A code snippet showing that Object.prototype has the property has own property.

A good example of this is the method hasOwnProperty on line 6. Notice that we call hasOwnProperty using dot notation, which means that hasOwnProperty is itself a property of an object. We prove that on line 7 by checking if Object.prototype has a property called hasOwnProperty which returns true.

In this case, the object foo inherits the property method hasOwnProperty from Object.prototype and can thus access the method. Object.prototype can be thought of as being like the grandfather of all objects as almost all objects are descendants of Object.prototype and therefore have access to its properties and methods. We will examine Object.prototype in more detail later in this article.

To summarise:

  • Objects have an internal property called [[Prototype]] that points to their prototypes.
  • Objects inherit properties and methods from their prototypes.
  • Almost all objects are descendants of Object.prototype and have access to its properties and methods.

Object prototypes vs Function prototypes

There are two types of prototypes in JavaScript which are easily confused. As we have already seen, one is a private property that each object has called [[Prototype]] that references that object’s prototype.

The other is a .prototype property that almost all functions have that is only used when that function is invoked as a constructor. I say almost all because arrow functions and methods defined using the concise syntax do not have .prototype properties and cannot be used as constructors. But what is a constructor function?

A constructor function is like an object factory that creates new objects which are instances of itself. You can see an example on line 6 of the following code block, where an object is implicitly returned by Factory and a reference to that object is stored in the descendant variable.

An image showing an object created using the constructor function factory.

We can access Factory's prototype property using dot notation, Factory.prototype . Upon logging the value of Factory.prototype on line 8 we see that it references an object. What is this object's purpose?

Each object instance that is created by Factory inherits from the object referenced by Factory.prototype. We can easily test this.

An image showing that descendants of a constructor function inherit properties of that functions prototype property.

Notice that on line 6 we add a new property called example to the object referenced by Factory.prototype. We use Factory to create a new object instance on line 9 and we store a reference to that object in the variabledescendant.

When we then log its value on line 10, we see that the properties foo and bar have been assigned to it. Notice that we can also access the property example through descendant on line 11 as it has inherited it from Factory.prototype .

So what do we learn from this?

  • Functions have a property called prototype which holds a reference to an object.
  • Any object instances created by a constructor function will inherit the properties of the object at FunctionName.prototype.

Function prototypes and Object.prototype

So where does the object referenced by Factory.prototype come from? Interestingly it is an object that is a descendant of Object.prototype.

On line 9 of the following code block we log the value of Factory.prototype's prototype, which is the object referenced by Object.prototype.

An image showing that a function constructor inherits from Object.prototype

We confirm that on line 11 by showing that Object.prototype and Factory.prototype's prototype both reference the same object and on line 15 where we show that Object.prototype is the prototype of Factory.prototype.

An image showing that descendant objects inherit from Object.prototype

We test this further by adding the property test to Object.prototype on line 16 which is the default object that almost all other objects inherit from. (This is not something you should do in your code, this is just an example that illustrates a point. I say almost all because it is possible to create an object that doesn’t inherit properties, but that is beyond the scope of this article).

Then on line 21 we can access that property through Factory.prototypeas Factory.prototype is a descendant of Object.prototype . We can also access the property test from descendant on line 23 as it inherits from Factory.prototype which in turn inherits from Object.prototype.

To summarize:

  • A constructor function’sprototype property is a descendant of the object referenced by Object.prototype.

Creating new objects

So what happens when you create a new object? When you create an object using the object literal syntax or using a constructor function, you are creating an object that inherits either directly or indirectly from Object.prototype.

As the Object constructor is itself a function, it has a property called prototype which can be accessed at Object.prototype . Object.prototype references an object, and almost all objects inherit properties from Object.prototype. You can think of inheritance as a chain, each object’s prototype references the next link in the chain until it reaches the default object at the top of the chain, Object.prototype.

Notice in the following code block we initialize an empty object using the object literal syntax and store a reference to that object in the variable obj.

An image showing that an object created using object syntax literals is a descendant of Object.prototype

On line 2 we log the value of Object.prototype which references an object. On line 3 we log the value of obj's prototype (or parent), which also references an empty object.

On line 5 we prove that the object referenced by Object.prototype and the prototype of obj are the same. And on line 6 we further prove that Object.prototype is the prototype of obj using the isPrototypeOf method.

That means that if we mutate the object at Object.prototype by giving it new properties, obj will also be able to access those properties (Again this is not recommended, it’s just being used to illustrate a point here). On line 8 we initialize the property foo of Object.prototype to the string 'Hey there!'.

We can test if the object has been mutated by logging the value of Object.prototype, where we see that the property foo has been successfully added. Now all descendants of Object.prototype have access to foo as we can see on line 11 when we access it from obj.

What does this example teach us?

  • Objects which are created using the object literal syntax inherit properties from Object.prototype .

Summary

So what have we seen?

  • Objects have a private property called [[Prototype]] that points to that object’s prototype.
  • Almost all objects inherit properties and methods from their prototypes.
  • Almost all objects are descendants of Object.prototype and therefore have access to its properties and methods.
  • Functions have a property called prototype which is a reference to an object. That object is a descendant of the object referenced by Object.prototype.
  • Any object instances created by a constructor function will inherit the properties of the object at FunctionName.prototype.

There are of course ways to change an object’s prototype such as Object.create or Object.setPrototypeOf, but that’s for another article. This article has only scratched the surface of prototypical inheritance, but hopefully it has helped you to understand the basic concepts.

Thanks for reading!

As promised here is the link to the code snippets used in the article: https://gist.github.com/eamon0989

--

--

Launch School
Launch School

Published in Launch School

Publications of the Launch School Community

Eamon O'Callaghan
Eamon O'Callaghan

Written by Eamon O'Callaghan

I’m a Software Engineer working at S1Seven. I mainly work with NestJS and TypeScript. I enjoy sharing what I’m learning by writing about it here!