Object-Oriented Programming in Javascript(ES5 & ES6) EXPLAINED.
Tags: javascript, es5, es6, oop
Published: 2020-04-28 12:59:43

#INTRODUCTION
OOP - Object-oriented Programming, in general, is very useful. It helps developers to model real-world things that we want to represent inside our code, and/or provide a simple way to access functionality that would otherwise be hard or impossible to make use of.
Getting a full understanding of how OOP works in javascript is a bit difficult especially in ES5 syntax, ES6 class made it a lot easier to use object constructor but as developers, we will run into ES5 object prototype codes along our journey and in case you do not know, ES6 class, work as object prototypes under the hood.

This article will explain javascript object in ES5 and ES6 syntax. Stay tuned!



###WHY USE OBJECT CONSTRUCTOR NOTATION?

You must have questioned the need for using object constructor and not stick with object literals. Well, object literals are easy and straight forward to understand but let's think of a scenario whereby we want to create an object from data gotten from an input field, for example; we have a website and in our website a form field that requests for the name, email, phone number, and address of our users. We want to use the data gotten from the form field to create an object as a way to keep user data together and then create a profile for each user and make sure each user should have the same properties(in this case name, email, number, and address). Using object literal notation requires us to create an object every time for each user, for instance from our form we got these data from three (3) users:
```
// 1st user
const user1 = {                               
  name: 'Precious',
  email: 'precious@gmail.com',      
  number: '+234-810-5025-740',
  address: 'Earth'
}

// 2nd User
const user2 = {                               
  name: 'Frank',
  email: 'frank@gmail.com',      
  number: '+234-800-5525-540',
  address: 'Jupiter'
}

// 3rd User
const user3 = {                               
  name: 'Charles',
  email: 'charles@yahoo.com',      
  number: '+234-810-4985-376',
  address: 'Mars'
}

```
The code is repetitive and that is against the DRY(Don't Repeat Yourself) principle of programming and we don't want that. The perfect solution to that is using object constructor notation, and then making **instances** of the object. Now let's write the above code using object constructor notation and how to make instances of an object:- 

```
// Object Constructor(ES5)
function User(name, email, number, address){
  this.name = name;
  this.email = email;
  this.number= number;
  this.address = address;
}

// Instances
// 1st user
const user1 = new User('Precious', 'precious@gmail.com', '+234-810-5025-740', 'Earth');

// 2nd user
const user2 = new User('Frank', 'frank@gmail.com', '+234-800-5525-540', 'Jupiter');

// 3rd User
const user3 = new User('Charles', 'charles@yahoo.com', '+234-810-4985-376', 'Mars');

```
From the above code, we just created, we used a **constructor** function which as the name implies is a function that constructs object **instances** to create objects from the data each user submitted in the form. It is DRY and clean with the constructor notation, and values from the object can be accessed with the same syntax
```
// OBJECT LITERAL NOTATION
// To get the name of the first user.
   console.log(user1.name) // Precious

// OBJECT CONSTRUCTOR NOTATION(ES5)
// To get the name of the first user.
   console.log(user1.name) // Precious
```


Let us explain some keywords that are used in the constructor notation.

1. The **this** keyword: In case you do not know before now, The **this** keyword in the constructor function above refers to the object itself i.e the user, meaning by saying **this.name = name** we mean the name property of that user should be set to the value of the parameter **name**. the **this** actually means different things in different context but inside the object constructor it is as stated above

2. The **new** keyword is simply used to instantiate(create) a new object from the constructor.



###OBJECT CONSTRUCTOR IN ES5 AND ES6

* <h4>ES5 Syntax</h4>
 1. Prototype and prototypal Inheritance:
 We have looked at how object constructor is written in ES5 syntax now let's look at what an object prototype is. 
Syntax:
```
function Dog(name, age){
 // Properties
  this.name = name;
  this.age = age;

 // Method
  this.canBark = function(){
    if(this.age => '180 days'){
       return 'YES';
    } else{
      return 'NO';
    }
  }
}

```
The method in the constructor function can better be written in javascript by writing it as a prototype like this:

```
function Dog(name, age){
 // Properties
  this.name = name;
  this.age = age;
}

// Object Prototype
  Dog.prototype.canBark = function(){
    if(this.age => '180 days'){
       return 'YES';
    } else{
      return 'NO';
    }
  }

```

Now, What is an Object Prototype? An object prototype is an object that is associated with every instance of an object by default in JavaScript. Prototypes allow you to easily define methods to all instances of a particular object. This is very useful in that the method is applied to the prototype, so it is only stored in the memory once, but every instance of the object has access to it.
We can also add a property to the object using a prototype which is not possible normally after declaring a constructor function, but it should only be used for properties we want all instances to share:
```
Dog.prototype.breed = 'German shepherd'

```

What if we have another object that we want to have all the properties and methods of the first object and their own special properties and/or methods, what do we do keeping DRY in mind?
The answer to that is provided by **prototypes** **inheritance** which simply means one object inheriting properties and methods of another. for instance, we want another group of dog to inherit some properties of the first group plus their own special properties(dog weight):

```
// Group 1
function Group1(dogName, dogAge){
 // Properties
  this.dogName = dogName;
  this.dogAge = dogAge;
}

// Object Prototype
  Group1.prototype.canBark = function(){
    if(this.dogAge => '180 days'){
       return 'YES';
    } else{
      return 'NO';
    }
  }

// Group 2
function Group2(dogName, dogAge, dogWeight){
  Group1.call(this, dogName, dogAge);
  this.dogWeight = dogWeight;
}

```
To Inherit the properties from the first group we used the call() method which is used to call the contractor we want to inherit its properties, and it takes in **this** as the first parameter and then the parameters to be inherited from that constructor(in this case:- dogName and dogAge). After which we then set the special property of the object(in this case: dogWeight);
This only inherits the properties and not the prototypes. To inherit the prototypes, we will say:

```
Group2.prototype = object.create(Group1.prototype);

```
With this, we have made the 2nd group of dogs possess all the properties and objects of the 1st group.



* <h4>ES6 Syntax</h4>
  Classes in ES6 is same as Object constructor function in ES5 under the hood that means both work in the same way just that ES6 has a much better syntax which one of my favorite tutor(Brad Traversy) calls "syntactic sugar" and also methods are directly made prototypes(made accessible to all instances of the Class). 
Now let's dive in ES6 classes.

1. Declaring an ES6 class & Constructor:

```
class Person{
  constructor(firstName, lastName, age){
    this.firstName = firstName;
    this.lastName = lastName;    // PROPERTIES
    this.age = age;
  }
    
   getAge(){
     return `${this.firstName} ${this.lastName};   // METHOD
   }   
}

```
KEYWORDS EXPLANATION:
A. **class** - is simply used to declare a class(ES6 object) it is followed by the name of the object.
B. **constructor** - Just as we used function in ES5 syntax. constructor is used construct the object.

NOTE: Value of objects in ES^ can be accessed in same way asin ES5 and also instantiation has the same syntax.

As simple as that looks we have just written our first object using ES6 class.


2. Inheritance:
  Inheritance in ES6 class has a different syntax and in involves using 2 new keyword **extends** and **Super**, let's take a look at it. if we want a customer object to inherit from the person object:

```
class Person{
  constructor(firstName, lastName, age){
    this.firstName = firstName;
    this.lastName = lastName;    
    this.age = age;
  }
    
   getAge(){
     return `${this.firstName} ${this.lastName};   
   }   
}

class Customer extends Person{
  constructor(firstName, lastName, age, memberShip){
    Super(firstName, lastName, age)   
    this.memberShip = memberShip;
  } 
}

```
KEYWORDS EXPLANATION:
A. **extends** : specifies that the Customer object inherit the properties and methods the Person object.
B. **super** : Just asin call() in ES5 objects, **super** states the properties inherited but here we don't have to use the **this** keyword.

NOTE: In ES6, we do not have to write a special line of code to inherit prototypes. as we already know, prototypes are accessible by all instances of the class object and so inherited by the extending class.

3. Lastly, let's talk about a special method available in ES6( **static** Methods):
Static methods come in handy when we have methods that do not make use of argument passed into instantiate(create an instance) a copy of an object and we want all instances of the object to have it. for example, if we want all instances of the Person object to have a tag of 'human' we will write:

```
class Person{
  constructor(firstName, lastName, age){
    this.firstName = firstName;
    this.lastName = lastName;    
    this.age = age;
  }
    
   getAge(){
     return `${this.firstName} ${this.lastName};   
   }   

   static isHuman(){
     return 'Is a Human'
   }
}

```
Just as simple as that. But mind you, Static methods are defined on the class itself, and not on the prototype.

That means you cannot call a static method with the instance but with the class itself e.g calling the static method in our class above will be 
```
Person.isHuman();   
```


#CONCLUSION:
I know this article was long, but I believe you have understanding of Object in ES5 and ES6 syntax; what object prototype mean, how to inherit from objects in ES5 and ES6, as well as ES6 class features and syntax.

Thank for reading, cheers!!!.