oop in javascript! part1: prototype
Sam aghapour
Posted on March 27, 2022
Hello friends😀
When I was learning Javascript, I’ve always wondered when I define a string or function, etc… how is it possible to get some properties and methods like length or search or forEach or any other methods?? When we see the backstage, we realize where all these come from. Finally, we find out a little bit about oop in javascript and what exactly is going on under the hood.
So we’ll explore oop in javascript in two parts. The first part is going to be about the prototype and setup for oop and the second part is just all about oop in javascript.
Javascript is an object-based language based on prototypes in contrast to other languages which are class-based.
This causes the Javascript object hierarchy and inheritance a little bit weird and complex. But what exactly are prototypes?
Let’s begin our journey with a simple example:
Here, I declared an object and logged its three properties, But wait a minute! I just declared a name and age property, where the hell is that hasOwnProperty method(object property which is a function called method) coming from? Hmmm…🤔 let’s log the whole object itself to see what it includes:
Well well well, look who’s here, now we can see when we define an object, javascript gives it a hidden but accessible property which is an object and called proto. Now let’s take a look at the proto_ property:
Here is where we can see the hasOwnPropert method and some other methods as well. The interesting thing is if we define thousands of objects with millions of properties, there is still going to be one more default property in all of them which is this object with all these methods and this object called ‘Global object prototype’ and what is more interesting is javascript is not going to define or in other word duplicate this object for every object we define, it is just going to give them proto property that references to global object prototype and in other word inherit global object prototype, so it will ensure to not blow up memory and what is much more interesting is if we look at global object prototype, it has proto property itself! Although it is null and kind of a reference to a dead-end, the point is there is no object that doesn’t have proto. Javascript is full of interesting things :)
Let’s investigate proto with different ways:
Object literal using object.create and object.setPrototypeOf methods
*1. using object.create: * **
So, we have a Car object with three properties or methods and nothing else. Then we declared a tesla variable and assigned it to object.create with 2 parameters, which is a Car object and the second parameter is an object with name property and value of tesla(it is a simple object but with a different shape of defining inside object.create), Let’s log tesla variable and see what object.create does:
As we can see, object.create defines an object with a name property and value of tesla using the second parameter, and this object’s proto is referred to the object we gave in object.create’s first parameter(which is Car object in this example) and the proto of the Car object is referred to global object prototype and proto of global object is referred to as null.
object prototype chaining
Remember, all prototypes are connected, no matter how nested they are going to be, at the end it comes to the global object prototype and then null and this is called object prototype chaining.
the second variable we defined is detail, Let’s just log it:
It is an object with its special property called speed and value of 3001, and its proto is referred to tesla, as you can guess from the example picture, and tesla’s proto is referred to Car object and Car object’s proto is referred to global object prototype and that is the prototype chaining.
Prototypal delegation
if you pay more attention to the example, you can see that detail can access to the name property of tesla object and car object but tesla can’t have access to detail’s speed property, and it’s because they only can have access or inherit objects that their prototypes are referred to. and it is a top to bottom relationship called Prototypal delegation.
so when we log tesla.speed, javascript is going to look for it inside the tesla object and if not find it, it will look for it inside its proto which is Car object and if there is no such property, it will keep looking for it inside other proto on the prototype chain which is global object prototype and if it isn’t there too, it will give us an undefined.
reason of annoying error known as ‘ ** is not a function’
As I explained above, when javascript can’t find a property inside the prototype chain, it returns an undefined. But if the speed property was a function (method) instead of number and javascript can’t find it, it will return an error 'tesla.speed is not a function'.
so when we call some methods on arrays or functions and javascript can’t find them, it returns an error and I’m sure you were in that situation that keep getting ‘ * is not a function’ before.
the third variable called volvo is going to have the same process as tesla has and the difference between volvo and tesla is just the name property’s value is volvo:
*2.using object.setPrototypeOf: * **
three variables (tesla,detail,volvo) that we defined above can be defined using object.setPrototypeOf( ) method:
In this use case, we define an object with its special property and value. Then object.setPrototypeOf’s first parameter selects the object which we want to manipulate its proto reference, and the second parameter is the object we want proto to be referred to.
So in the above image, we select tesla and set its proto reference to Car object, select detail object and set its proto to tesla object, and then volvo object’s proto to Car object.
Constructor function using new keyword
Functions are function and object!
Functions can behave like an object because when we define them, javascript gives them a bunch of methods and properties, and as you can see, I defined a Car function and gave it name property.
Now let’s investigate the above image:
When there is a function whose name is capitalized and it has the ‘this’ keyword inside, we tell javascript that this is an object and can be instantiated by using the new keyword. By putting ‘this’ inside the constructor function, we tell javascript every object that has instantiated from this function ‘this’ will be referred to as that object.
In the example above, defining tesla with the new keyword and Car() function and ‘ this.name ‘ inside Car function is something like “hey javascript, tesla should have a name property and its value should be whatever it passes as an argument, as well as volvo.”
The car function is called the Constructor function.
Hey, we missed that prototype part, what about that????🤔
In the above example, we are manipulating the Car object’s proto. So when Car becomes any object’s proto’s reference, it is going to be an object containing those methods that we gave to the Car prototype.
Note that name is not in proto object, name is something we need to give to each object we defined with its special value.
Let’s log tesla and see the result:
When we instantiated the Car as tesla, we created the object with the name property and value of tesla and its proto is referred to Car prototype which is an object with three methods that we defined and this object is referred to global object prototype. the same process is true about volvo.
Note that without new keyword we can’t instantiate constructor function and new keyword is the one who creates an object and refers “this” keyword to object that it created and adds Car’s prototype to object’s proto that it created.
Now the main reason why we have prototypes?
Imagine we want to declare thousands of objects with name property and some methods that all of them should have and all of those methods are doing the same thing as other objects’ methods.
Do you think it is a good idea to declare all of those objects one by one and define all those methods one by one for every object? Hell no! this will kill the memory.
by using constructor function and prototypes we just have to declare one object with all methods we need and let other objects just inherit these methods and use them.
in the above example we are not declaring volvo object and tesla object and each of them with three methods, we just instantiate Car and inherit methods from it.
note that ‘this’ keyword inside sayName method is referred to the object that inherit it.
note that in above example at last line, we are logging tesla.noneFunction method, So javascript is going to look for it in its prototype chain and if not find it, will return ‘tesla.noneFunctoin is not a function’.
and yes! Global object prototype is one prototype object containing methods for all objects in javascript.
difference between proto and prototype
We have gone so far, I’m not going to leave you with this question without an answer. Although you may have already noticed the difference.
Prototype just exists on a function and is defined as a property when a function is declared. A prototype is just an object of methods we give to the constructor function as a reference for its instance object’s proto.
as we can see Car.prototype is the same tesla.proto , because tesla is an instance of the Car and its proto is referred to Car.prototype.
proto for objects and prototype for functions.
ES6 classes using the new keyword
Now, we are getting closer to the oop area… In many programming languages, we have a concept called oop or object-oriented programming which is a paradigm for designing programs using classes and objects.
Classes are introduced in ES6 and made Javascript able to use oop, but it just fakes it and makes it look like oop, but it is totally different under the hood and javascript uses the same prototype process we already knew about it. In other word, javascript has oop but in its own way:)
Now, let’s see the prototype process with classes and new syntaxes to get a better understanding of what oop looks like and how the prototype and inheritance process happen:
I declared a class called Car, and inside this class, we have a constructor. This is the same constructor function we saw earlier:
And the methods we declared inside Car class, is like we set the prototype of Car to some methods but more easily and cleanly:
Now Let’s talk about this part:
Well, you already know the ‘new’ keyword and what it does.
It instantiates Car and creates a new object with name property and value of tesla, and a proto object which is referred to an object containing those three methods that we declared inside Car class and another proto object that is referred to Global object prototype… same for volvo.
Then, we declare another class called Detail with its special property named speed and by using extends and super() we inherit all things inside Car class including name property and proto object of three methods.
Here is the result of logging the detail object that is instantiated from the Car object:
This is how javascript implements oop :)
We learned about the prototype and what it is and how you can take advantage of it in many different ways in javascript.
In the next part, we will explore the four pillars of oop and all the things we need to know with real-world and code examples.
Until the next part, Goodbye and Good luck🤞
Posted on March 27, 2022
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.