What are Classes?

Classes is the new way of writing constructor functions in JavaScript. It is syntactic sugar for using constructor functions, it still uses prototypes and Prototype-Based Inheritance under the hood.

   //ES5 Version
   function Person(firstName, lastName, age, address){
      this.firstName = firstName;
      this.lastName = lastName;
      this.age = age;
      this.address = address;
   }

   Person.self = function(){
     return this;
   }

   Person.prototype.toString = function(){
     return "[object Person]";
   }

   Person.prototype.getFullName = function (){
     return this.firstName + " " + this.lastName;
   }  

   //ES6 Version
   class Person {
        constructor(firstName, lastName, age, address){
            this.lastName = lastName;
            this.firstName = firstName;
            this.age = age;
            this.address = address;
        }

        static self() {
           return this;
        }

        toString(){
           return "[object Person]";
        }

        getFullName(){
           return `${this.firstName} ${this.lastName}`;
        }
   }

Overriding Methods and Inheriting from another class.

//ES5 Version
Employee.prototype = Object.create(Person.prototype);

function Employee(firstName, lastName, age, address, jobTitle, yearStarted) {
  Person.call(this, firstName, lastName, age, address);
  this.jobTitle = jobTitle;
  this.yearStarted = yearStarted;
}

Employee.prototype.describe = function () {
  return `I am ${this.getFullName()} and I have a position of ${this.jobTitle} and I started at ${this.yearStarted}`;
}

Employee.prototype.toString = function () {
  return "[object Employee]";
}

//ES6 Version
class Employee extends Person { //Inherits from "Person" class
  constructor(firstName, lastName, age, address, jobTitle, yearStarted) {
    super(firstName, lastName, age, address);
    this.jobTitle = jobTitle;
    this.yearStarted = yearStarted;
  }

  describe() {
    return `I am ${this.getFullName()} and I have a position of ${this.jobTitle} and I started at ${this.yearStarted}`;
  }

  toString() { // Overriding the "toString" method of "Person"
    return "[object Employee]";
  }
}

So how do we know that it uses prototypes under the hood?

   class Something {

   }

   function AnotherSomething(){

   }
   const as = new AnotherSomething();
   const s = new Something();

   console.log(typeof Something); // logs "function"
   console.log(typeof AnotherSomething); // logs "function"
   console.log(as.toString()); // logs "[object Object]"
   console.log(as.toString()); // logs "[object Object]"
   console.log(as.toString === Object.prototype.toString); 
   console.log(s.toString === Object.prototype.toString); 
   // both logs return true indicating that we are still using 
   // prototypes under the hoods because the Object.prototype is
   // the last part of the Prototype Chain and "Something"
   // and "AnotherSomething" both inherit from Object.prototype