OOPs in general
In the classical Object-Oriented Programming model with classes and instances created from these classes. And remember, a class is like a blueprint which is a theoretical plan and that we use to build many houses in the real world. And in the same way, the theoretical class can be used to create actual objects which are called instances and which we can then use in our cout. And this process of creating an instance is called instantiation.
OOPs in javascript
In JavaScript, things work a bit differently. So why did I first tell you about classes and instances? Well, it's because we do have similar concepts in JavaScript and so it's very useful to first understand the class instance model. in the context of JavaScript. And finally, JavaScript syntax itself uses also some of these terms for example, instances.
How does OOP actually work in JavaScript? Well, in JavaScript we have something called prototypes and all objects in JavaScript are linked to a certain prototype object. So we say that each object has a prototype.
And now here comes the magic. So, the prototype object contains methods and properties that all the objects that are linked to that prototype can access and use. And this behavior is usually called prototypal inheritance. So, again, prototypal inheritance means that all objects that are linked to a certain prototype object can use the methods and properties that are defined on that prototype. So basically, objects inherit methods and properties from the prototype which is the reason why this mechanism is called prototypal inheritance. Just note that this inheritance is actually different from the inheritance of OOPs in general . So that was one class inheriting from another class. But in this case, it's basically an instance inheriting from a class. So that's very different and so keep that in mind. Alright? Now we can also say that objects delegate behavior to the linked prototype object. And behavior is just another term for methods here. So besides prototypal inheritance, we also call this mechanism, delegation. And that's also the reason why in digram 2 this arrow is pointing upwards because technically, objects delegate their behavior to the prototype. On the other hand, in classical OOP with classes, the behavior, so the methods, are actually copied from the class to the object and so that is completely different.
And by then, am sure that all this will make 100% sense to you.
We have actually already seen this mechanism in action many times before but without knowing that it was happening. For example, each time that we used an array method like map, we are able to use that method because of prototypal inheritance. So, when you go to MDN to check the documentation for any array method, what you will see there is that it's actually called array.prototype.map. But why is that relevant? So, what does this mean? Well, array.prototype is the prototype object of all the arrays that we create in JavaScript. So, just like this example array called num. Now, this prototype object contains all the array methods, including map. So, this is where they are actually defined. So, since array.prototype is the prototype of the num array, it means that num is linked to that prototype. And therefore, it has access to all the methods that are defined on the array.prototype object, just like the map method. So, in a sense, our array inherits the map method. Or again, we can also say that the array delegated the behavior of mapping to its prototype. So, you can choose whatever makes more sense in your mind. But what matters, is that the map method is actually not defined on the num array itself but on its prototype. Right now, you might have a ton of questions in your head. Like, how do we actually create prototypes? And, how do we link objects to prototypes? And how can we create new objects without having classes from which we can instantiate objects?
So, in summary, the question is how do we implement Object-Oriented Programming in JavaScript in practice? Well, in JavaScript there are actually three different ways of doing all this: the constructor function technique, ES6 classes and also the Object.create(). So first, constructor functions are a way of creating objects programmatically, using a function which will also set the new object's prototype. And this is actually how built-in objects like arrays or maps or sets are implemented. Also, this is how OOP has been done in JavaScript basically since the beginning. Next, the ES6 release introduced classes into JavaScript. And so now, ES6 classes are actually the more modern way of doing OOP in JavaScript.
However, keep in mind that these are actually not the kind of classes. They are instead just so-called 'synthetic sugar' over constructor functions. So this means that ES6 classes are basically just a layer of obstruction over constructor functions. So, it's really just a nicer syntax that makes it easier for newcomers to do OOP in JavaScript. But behind the scenes, ES6 classes are actually implemented with constructor functions. And so they also use prototypal inheritance just like we learned in figure 2. Finally, there's also the object.create() which is basically the easiest and most straightforward way of linking an object to a prototype object. However, it's not as used as the other two methods. Now, to finish, one important thing to keep in mind is that the four principles of Object-Oriented Programming abstraction, encapsulation, inheritance, and polymorphism are still valid and important with prototypal inheritance. And throughout this section, we will of course learn how to use and implement these principles. Alright.