Introduction to OOP in Javascript

Written by andresporras | Published 2020/04/21
Tech Story Tags: javascript | ecmascript-6 | oop | classes | object-oriented | tutorial | beginners | coding

TLDR Javascript used to be, just a few years ago, one of the most disliked languages by the community. ECMAScript 6 introduced in 2015, we have a modern syntax to create classes. Inheritance means that you can inherit methods and properties from a different class (or many different classes) Child classes will extend the behavior of its parent class. Encapsulation, polymorphism, abstraction and inheritance are four concepts in OOP languages. Never forget these four concepts: inheritance, encapsulation, and polymorphism.via the TL;DR App

Javascript used to be, just a few years ago, one of the most disliked languages by the community, it's unnatural behavior was a common inspiration for jokes between developers. One of the main complaints was about the lack of a simple syntaxis to work with classes.
WHY OOP?
Most of the popular languages use the OOP philosophy, many companies need employees who can comprehend how to work using classes. Some of the most common questions in interviews for developer positions are related to a basic understanding of how OOP works.
The core concepts of object-oriented programming languages (inheritance, encapsulation, polymorphism, abstraction) will be always present in our job as software developers as long as you work with a language that let you declare a class, even if you don't use it frequently, these concepts will be there in the libraries, frameworks, in that project that you have to maintain.
The solution with ECMAScript 5 was to use prototypes that simulate the class behavior, but the generated code was long and hard to understand, and maintain. for some other developers, the solution was to work with Typescript or some other superset of javascript.
let pepe= {name:"pepe", age:12, getData: function(){return "name: "+this.name+", age:"+this.age}};
console.log(pepe.age); //12
console.log(pepe.getData()); //name: pepe, age:12
Thanks to ECMAScript 6, introduced in 2015, we have a modern syntax to create classes. Let's see a simple example of the basic structure:
    
class book{
constructor(name, price, autor){
this.name=name;
this.price=price;
this.autor=autor;
this.giveMessage = (amount)=> "total price is:"+(amount*this.price);
}
}
book1 = new book("Harry Potter", 300, "JKR");
console.log(book1.name); // Harry Potter
console.log(book1.giveMessage(5)); // total price is: 1500
console.log(book1 instanceof book); //true
If you have work with OOP languages before you will quickly get the basics concepts present here. "First of all, the class definition in the first line, secondly the constructor of the class which receives the initial parameters, third the creation of the variables and methods, and lastly the creation of an instance.
With "<instance> instanceof <class>" we can check if <instance> is an instance of the class <class>, then it returns true, otherwise false. In this article I don't want to focus on those basics concepts, instead, I want to talk about the four fundamental concepts in OOP:
  • Inheritance
  • Encapsulation
  • Abstraction
  • Polymorphism
Inheritance in Javascript
In OOP, inheritance means that you can inherit methods and properties from a different class (or many different classes). Child classes will extend the behavior of its parent class. In the next example, cat class inherit can use the properties and methods from its parent class, animals:
class animals{
    constructor(size, kilograms, name){
    this.size=size;
    this.kilograms=kilograms;
    this.name=name;
    }
    
    givePounds(){
    return this.kilograms*2.2046;
    }
    }

class cat extends animals{
    constructor(size, kilograms, name, race){
    super(name, kilograms, name);
    this.race=race;
    }
    weightMessage(){
    return "this cats weights "+this.kilograms+" kgs or "+super.givePounds()+" lbs.";
    }
    } 

    let c = new cat(10,30,"pepe","russian");

    console.log(c.name); //pepe

    console.log(c.weightMessage()); //this cats weights 30 kgs or 66.138 lbs.
With "extends" we indicated the parent class, with super we pass the parameters to the parent class when we create an instance of a cat class.
Abstraction in Javascript
Different to the other concepts, abstraction is still not clearly defined in ECMAScript 6, but there is a way to implement its behavior:
class AbstractArtist {
 
 constructor(name) {
    if (this.constructor === AbstractArtist) {
            throw new TypeError('Abstract class "AbstractArtist" cannot be instantiated directly.'); 
        }
     this.name = name
 }
}

class musician extends AbstractArtist {

 constructor(name, last_album) {
     super(name);
     this.last_album = last_album;
     console.log("artist: "+this.name+", last album: "+this.last_album);
 }
}


juanes = new musician("juanes","mi tierra"); // artist: juanes, album: mi tierra

jose = new AbstractArtist("jose"); // throw error

console.log(jose.name);
This way, the "abstract class" throws an error when it's instantiated, but it works when another class uses it to be extended.
Polymorphism in Javascript
Polymorphism is the capability to perform a single action in different ways. Other languages like Java and C# are type-safe and the overriding requires some special syntax. But in javascript this is performed more directly, let's see an example:
    class country{
        constructor(size, population){
            this.size = size;
            this.population = population;
            this.giveDensity = () => "this country has "+(this.population/this.size)+" citizens for each square kilometer";
        }
    }

    class englishCountry extends country {
        constructor(size, population){
            super(size, population);
            this.giveDensity = () => "this country has "+(population*0.621371/size)+" citizens for each square mile";
        }
    }
    
    let japan = new country(377975, 126150000)
    let usa = new englishCountry(9833520, 328239523)

    console.log(japan.giveDensity());
    console.log(usa.giveDensity());
Class "englishCountry" overrides the default behavior of the method "giveDensity" of its parent class "country".
Encapsulation in Javascript
Giving free access to parameters of a class can be inconvenient sometimes... Once in a while, we will need to keep safe some attributes or methods. To do this we could declare them as private, in this way the users can not directly access those attributes and methods.
In the next example, I will show how to have indirect access to a private attribute using setters and getters:
    class Person  {
        #name; //must be declared
        constructor (name)  {
            this.#name = name;
            this.getName = ()=> this.#name;
            this.setName = function(newName){
                if (newName.length>0){
                    this.#name = newName;
                }
                else{
                    console.log("invalid name");
                }
            }
        }
    }    

    let person = new Person("oscar", "porras");
    console.log(person.getName()); //oscar
    person.setName("andrés");
    console.log(person.getName()); //andrés
    person.setName(""); //invalid name
You must use "#" to declare a private variable or method. Once declared, you cannot edit or read this variable just by using its name. If you need to edit or read this variable you will need to use the get and set methods. In the example, I created the method "getName" and "setName" to read and write the private variable. Notice that the write method doesn't allow you to edit if the new name length is 0.
CONCLUSION
As a software developer, working with OOP language, you must never forget these four concepts: inheritance, abstraction, encapsulation, and polymorphism. Pure theoretical definitions can be confusing the first time, that's why I like explaining with examples. Never forget trying to use these core ideas in your code, if you can apply them then probably is because you should do it.

Published by HackerNoon on 2020/04/21