When I first started learning Javascript and OOP I heard over and over that Javascript is an object-oriented language though it is not based on classes but prototypes.
In this article we are going to try to understand what this means and why it is important to know what a prototype is to acknowledge what we are doing.
In other object-oriented languages when you declare a class you are creating a new complex data type, that is to say, a data type composed of primitive data types. But this is not what happens in Javascript even though we use the keyword class since ES2015. Prototypes are object instances. While a class is a blueprint, objects inherit directly from other objects by default in Javascript.
To understand what this means, we need to understand what the prototype chain is.
The prototype chain is a tree-shaped structure that connects objects functionality and at the root of this tree is where Object.prototype lays.
Object.prototype provides a few methods that show up in all objects, such as toString( ), hasOwnProperty( ) or keys( ).
Almost every object in Javascript is an instance of Object if we follow the prototype chain. And as you probably know, almost everything in Javascript is an object, even some primitive data types (string, boolean and number specifically) can be objects for a tiny fraction of time. So, arrays are objects, functions are objects and, of course, objects are objects.
The prototype chain allows us to create instances of, for example, arrays that have access to all the methods that are available for arrays, like map, forEach, reduce, filter, and a big etc. But arrays also have access to all the Object.prototype functionalities.
How does this happen?
Just to be clear because we are using arrays for the example, arrays are syntactic sugar in Javascript. They are objects with a special behavior to make them look and feel like an array, but under the hood, they are something like this:
{
'0': value,
'1': value,
'2': value
}
It turns out that every object has a property called __proto__ which holds a reference to the prototype object of the constructor. So following the array example, an array has access to all the methods in Object.prototype because every array is an instance of the Array object and the Array object is an instance of the Object object. And this chain goes on until we hit the prototype of Object.prototype which will be null.
This way, when we try to execute a method on an object, first JS will lookup in the properties of the object itself. If it doesn’t find a property with that name, it will look in its __proto__ property, which holds a reference to the prototype object of its constructor. If it doesn’t find it there it will look in the __proto__ property of the constructor object. This will go on until it finds it or it doesn’t find it and throws a TypeError.
What this means is that, for example, every time we declare an array we are creating an instance of the Array object that comes with the language. if we look at it in the console we will see that its __proto__ property is linked to the Array object:
And if we keep looking down the rabbit hole we’ll see that the __proto__ object has a __proto__ property itself that holds a reference to Object.prototype (it’s a reference even though you see all the properties in the console because you know, DRY).
So, is there a way to create an object without a prototype in Javascript?
Well, yes there is. One of the ways of creating an object is with Object.create( ), to which we can pass as an argument the prototype we want that object to have, which by default is Object.prototype. If we pass it null as an argument we will get an object that is just that, a hash table.
const objectWithoutPrototype = Object.create(null);
Share if you liked it and let's connect! Follow me on Twitter and LinkedIn 😊
Top comments (0)