OOP In JavaScript
Maybe you already know what OOP (Object Oriented Programming) means, but it won’t harm to explain it again. By OOP we mean to use self-contained pieces of code in order to make the programs we want. It is like making a big app with small programs (Ok, programs is not the word but it is just for the newbies to understand). These pieces of code are called objects but many programming languages call them Classes and in JavaScript we call them functions. Using these pieces of code is like building a big LEGO, you use small pieces of code to make a big one.
Why is OOP useful? First thing, we can call the same piece of code several times when we need it. This is great because it saves us time and lines of code. Writing more code than we should may lead to time wasting and finger injuries. No way! As long as we can save our time and our effort, it is always a good thing to do. Basically, these techniques are called Inheritance, Polymorphism and Encapsulation. We will explain them in this article as how they are useful for OOP in JavaScript.
Encapsulation and Inheritance
These two techniques are the best to be implemented in OOP with JavaScript because JavaScript has several functionalities especially designed for them. In JavaScript, objects can encapsulate functionalities (making them responsible for specific tasks) and inherit properties and features from other objects. Of course there are many other techniques for OOP in JavaScript but these 2 are very useful and this scripting language is made to use them.
In JavaScript almost everything is an object and when you look at a JavaScript snippet you are going to see many of these around. Functions, Numbers and Strings are considered objects. These are like the building blocks of our app and we have to arrange them to develop it. It looks simple, and once you know how to OOP in JavaScript you will discover how nice it is.
Encapsulation means you put all the functionalities of a Function (the way we call objects in JavaScript) within that function so we don’t need to see that code around everywhere and just call it when we need it. When we need a function and we put it to perform its tasks we usually say we “call” it. We can also say we execute it or we invoke it. I much prefer calling but it is a matter of tastes, it all means the same.
Inheritance means a function can inherit properties or methods of another function. This is really useful because it saves us time and coding. As the code is reused, we don’t need to type it again and not even copy/paste it. This is much more efficient than writing lines and lines of code. A function that inherits from another function is called the child and the one that is passing its properties is the father function. They don’t need to be exactly the same, the child can have some different properties than the father but has inherited some or all the properties from the father.
For example, if we have a function named cars, we can create a child one named Chevrolet. Since it is a car, it inherits the properties of the father. This is what we call an instance. In this case, Chevrolet will inherit the properties and methods of Cars. How do we apply this to OOP in JavaScript? Keep reading…
Prototypal OOP
There are different ways to approach OOP and different programming styles. Usually in class-based scripting languages the most common way is to use the constructor pattern. This looks pretty good for all those who are used to class-based languages but in the long run will cause problems when working in JavaScript because what is really happening is a prototypal OOP even you didn’t notice. This doesn’t take the most of JavaScript so, if you plan to OOP in this language you’d better get used to the prototypal system.
The main difference is that by using the constructor system you are actually using objects (there are only objects in JS) and so that you have the objects already, why not to use the prototypal system. In the classic way when we want to implement inheritance what we do is to create a class as a blueprint and then we add more objects by using that blueprint. Actually the blueprint is not usable, because it is just intended to create more objects out of it.
With the prototypal system we only create objects and with these objects we create more objects. Let’s say we want to create a set with many different tables. In constructor based system we will create a blueprint for the basic table and then add different features like extra legs. With the prototypal system we will create planks and we will make different tables with these planks. When we have a table with 4 legs we can also add 2 more planks to it and we have a table with 6 legs.
Even though you may be tempted to use the classic constructor system, when we are trying to OOP in JavaScript we should implement prototypal OOP. The language is based in objects, not in classes so using the objects as much as possible is much better and goes with the flow of the Scripting language.
EXAMPLES OF PROTOTYPAL PROGRAMMING
Let’s make an example of how to do the same with the constructor and the prototype system.
We will create an object named car and then we will give it some values:
function Car () {}
Car.prototype.brand = "Chevrolet";
Car.prototype.model = "Corvette";
Car.prototype.firstReleased = new Date();
Car.prototype.NewInStock = true;
Car.prototype.fullModel = function () {
console.log (this.brand + " " + this.model);
};
var Chevrolet = new Car ()
console.log(Chevrolet.fullModel());
console.log(Chevrolet.NewInStock);
Or you can use a constructor function to do it. In JavaScript they are called functions instead of classes like in many other scripting languages:
function Car (brand, model) {
this.brand = brand;
this.model = model;
}
var chevroletCorvette = new Car (“Chevrolet”, “Corvette”)
console.log(cheveroletCorvette.brand);
console.log(chevroletCorvette.model);
In this case, Car is what we call the constructor function and chevroletCorvette is a newly created object with the constructor function. The console log will prompt us Chevrolet and Corvette when we use the console.log function.
This is a useful way to create objects if what we need is to add properties or methods to them and also it is useful to encapsulate them. There are many ways to deal with these constructor functions and we will review the most used of them.
The main point of all of this is inheritance, which means we save code by reusing it. In the example shown above we will likely want to add more cars and all of them will share the brand and model and many of them may be Chevrolet brand or even Corvette model. Reusing code or inheritance is the most efficient way to save our time and energy for better things than typing the same thing over and over again.
Encapsulation is also very useful when OOP programming. We want to encapsulate when we are going to have many objects sharing the same properties and methods and the best way to do this is a constructor function. If we do this, we don’t have to define these methods again for each object (so, in the end we come back to the same point, we don’t want to type more code than we strictly need).
In this case we will use a combination of both methods in an object oriented pattern to build an application of RPG users who play some game. Of course first we need players who are going to play the game and some of their properties and methods are going to be the same. The real name, the nickname and their level. These will be all properties of the Player object (will be considered a class in other programming languages), besides this the app should also save the level of the player and change their nickname if they want to do so as well as show their name and their level. These are shared methods for every Player and since all our players will share these properties and methods we can use a constructor to encapsulate them and save our time and energy.
function Player (theName, theNicknamel) {
this.name = theName;
this.nickname = theNickname;
this.levelUp = [];
this.hisLevel = 0;
}
Player.prototype = {
constructor: Player,
saveLevel:function (theLevelToAdd) {
this.levelUp.push(theLevelToAdd)
},
showNameAndLevels:function () {
var Levels = this.levelUp.length > 0 ? this.levelUp.join(",") : "You didn’t play yet.";
return this.name + " Level: " + level;
},
changeNickname:function (newNickname) {
this.nickname = newNickname;
return "New Nickname Saved: " + this.nickname;
}
}
So now let’s take a look line by line to the piece of code to better explain it. First thing we need to initialize the properties. These properties will be shared among all players but each player will have different values. When we use the keyword “this” we are indicating that the property is going to be different for each player. Or said in another more technical way, every instance of the Player object will have different values.
this.name = theName;
this.nickname = theNickname;
this.levelUp = [];
this.hisLevel = 0;
In the following code we are defining the methods to be used for every player. We are overwriting the constructor in a way that we don’t have to use the keywords Player.prototype all the time. Because it means more typing and more energy and time wasting.
Player.prototype = {
constructor: Player,
saveLevel:function (theLevelToAdd) {
this.levelUp.push(theLevelToAdd)
},
showNameAndLevels:function () {
var Levels = this.levelUp.length > 0 ? this.levelUp.join(",") : "You didn’t play yet.";
return this.name + " Level: " + level;
},
changeNickname:function (newNickname) {
this.nickname = newNickname;
return "New Nickname Saved: " + this.nickname;
}
}
By doing this we can create as many instances as we want from the Player object and they will all inherit the same properties and methods. They are all encapsulated in the object so, all the code there will be reused over and over again when we want to create a new player (instance). Saving lines of code and also saving our energy for better things than typing useless code.
Let’s create some players so you will see how useful it is:
firstPlayer = new Player("Hugo", "Urloc");
firstPlayer.changeEmail("Urloc_San");
firstPlayer.saveLevel(15);
firstPlayer.saveLevel(10);
firstPlayer.showNameAndLevels();
secondPlayer = new Player("Tommy", "Flashguy");
secondPlayer.saveLevel(18);
secondPlayer.showNameAndLevels();
As you can see, we have already created two players and all of them already have the same properties and methods, without having to define them twice. This will be even more useful if we want to create 100 players. All of them have a name, nickname and the levels won on each game and they can all show the levels and can also change the nickname but retaining the original name. This is called inheriting the methods and again, saves our time and energy for better things.
What is really great about this is the objects share the same methods and properties by default but we can create more for each of the players, while others don’t have them. The “child” objects inherit all the properties and methods from the father object but they don’t have to be exactly the same, they can have their own properties and methods. Look at the objects like building LEGO blocks, once you have one defined you can use it to build another more complex model but reusing the old model we had.
CONCLUSION
JavaScript is a great language for OOP programming but if you plan to OOP in JavaScript you must understand the prototypal OOP. Encapsulation and inheritance are as important as in any other scripting language and there is not a general consensus on which one of class based or prototype based programming is better, but I think that should go with the programming language we are using at the moment. JavaScript is object-based and doesn’t even understand classes. Even though you can “fake” them and make objects look like classes, it is only logical you use the best resources of JavaScript and you implement prototype programming instead.
Recent Stories
Top DiscoverSDK Experts
Compare Products
Select up to three two products to compare by clicking on the compare icon () of each product.
{{compareToolModel.Error}}
{{CommentsModel.TotalCount}} Comments
Your Comment