Classes and Prototypes in JavaScript

Classes and Prototypes in JavaScript

A JavaScript class is a blueprint for creating objects. A class encapsulates data and functions that manipulate data. It determines what the properties of an object are and how it behaves.

It was introduced in EcmaScript 2015 (ES6)

Defining Classes

To declare a class, you use the 'class' keyword with the name of the class.

There are two ways of defining classes:

  • Class declarations

    class User{
    constructor(param){
      // methods and properties
    }
    }
    
  • Class expressions

    let User = class{
    constructor(param){
      // methods and properties
    }
    }
    

Classes are in fact "special functions", but an important difference between functions and classes is that while functions can be called in code that appears before they are defined (Hoisting), classes must be defined before they can be constructed.

Creating New Objects using Classes

The 'new' keyword creates a new object with all the properties and methods defined in the class. All the properties associated with the objects need to be defined inside the constructor() function.

// Defining a class named 'User'
 class User{
  constructor(param){
    // methods and properties
  }
}

// Creating objects from the User class
let  User1 = new User();
let  User2 = new User();

Class Body and Method definitions

All the code inside the curly brackets { } after the class name is considered to be the body of that class.

Constructor

The constructor() is where you can initialize the properties of an instance. JavaScript automatically calls the constructor() method when you instantiate an object of the class.

Every class always contains a default constructor(), and every class can contain only a single constructor() method. If you try otherwise, it will throw a SyntaxError.

Constructor() can be with:

  • No parameters
constructor( ) { }
  • Parameters
    constructor(para1 , para2) {
    this.para1 = para1;
    this.para2 = para2;
    }
    
  • Parameters with default Values
    constructor(para1 = 'default value 1' , para2 = 'default value 2') {
    this.para1 = para1;
    this.para2 = para2;
    }
    

JSClasses1.png

In the above illustration:

  • A class is declared with the name 'Car' and this class can be used to instantiate as many objects as want from it.

    By the use of classes code can be made reusable and less complex.

  • Then a constructor() is defined with all the properties.
  • Then a method a is defined, and now our class is fully defined and ready to use.
  • Now, we can make as many objects of 'Car' as want ( as you can see in lines 19 - 26).

Getters and Setters

  • Getter: getter methods are used to access the properties of an object.
// Syntax for Getter
get getterName( ){ }
  • Setter: setter methods are used to change the values of an object.
    // Syntax for Setter
    set setterName(parameter){ }
    

In the above illustration:

  • On line 15 a getter method 'getPrice()' is defined.
  • And on line 29 getter is called.

    Note: If we try to call the getter by "Car1.getPrice()" it will give an error, the correct way to call the getter is "Car1.getPrice;".

  • On line 20 a setter method 'setPrice()' is defined.
  • And on line 33 setter is called.

    Note: If we try to call the setter by "Car1.setPrice(3.4)" it will give an error, the correct way to call the setter is "Car1.setPrice = 3.4;".

Inheritance

Inheritance is a functionality that allows a class to acquire all the properties and methods of another class. We use the keyword 'extends' in a class declaration or a class expression to create a child class of another class.

The class that inherits is known as Child Class and the class from which inheritance is done is known as Parent Class.

Untitled (8).png

Super(): The keyword super() is used to access the properties in the Parent class or invoke the constructor() of the Parent class. It calls the parent class's constructor and binds the parent class's properties, after which the derived class's constructor can further access and modify using the 'this' keyword.


Prototypes in JavaScript

Prototypes are the mechanism by which JavaScript through which objects inherit features from one another.

A prototype is basically an object (also known as a Prototype object), where we can attach methods and properties to a prototype object, which enables all the other objects to inherit these methods and properties.

Nearly everything in JavaScript is an object other than six things that are not objects which are — null, undefined, strings, numbers, boolean, and symbols. These are called primitive values or primitive types. Anything that is not a primitive value is an Object. That includes arrays, functions, constructors, and objects themselves.

And when an object is created in JavaScript, the JavaScript engine adds a prototype property to the function. This prototype property is also an object (called a prototype object).

We can access the prototype property of any function using 'functionName.prototype'.

let array = [1,2,3,4,5];
function student (name, roll) {
  this.name = name;
  this.roll = roll;
  return `Student name: ${this.name} Student roll: ${this.roll}`;
}

let student1 = new student('Bond', 7);

let objectLiteral = {
  firstName: 'James',
  lastName: 'Bond'
}

In the browser's console:

console.log(array)

Untitled (13).png

// To access the prototype of any function: 'functionName.prototype'. student.prototype

Untitled (16).png

console.log(student1)

Untitled (14).png

console.log(objectLiteral)

Untitled (15).png

If we type the object's name followed by a period into the console, like objectLiteral., then the console will pop up a list of all the properties available to this object. We have only defined two properties in objectLiteral, firstName and lastName yet we were able to see and access a lot more properties.

__defineSetter__
__lookupGetter__
__lookupSetter__
__proto__
city
constructor
greet
hasOwnProperty
isPrototypeOf
propertyIsEnumerable
toLocaleString
toString
toValueOf

These properties are coming from the prototype object.

Untitled (15).png

Since the prototype is itself an object, so the prototype will have its own prototype. In the [[prototype]] object we can see that there is one more property named 'proto: object', this is the prototype object of the [[prototype]].

And this is known as Prototype-Chain. The chain ends when we reach a prototype that has null for its own prototype.

Untitled (16).png

Prototype Chain

When we try to access a property of an object:

  • The property is searched in the object.
  • If the property can't be found in the object itself.
  • The property is searched in its prototype.
  • If the property still can't be found, then the prototype's prototype is searched, and so on until either the property is found, or the end of the chain is reached, in which case, 'undefined' is returned.

Adding Properties and Methods using Prototype

proto.png

In the above illustration, we can see that on line 8, we added a new property. And on line 11, we added a new method using the prototype.

Untitled (17).png

We can also add properties and methods to objects globally.

proto1.png

The properties and methods added using this 'Object.prototype' is available for access to every object in the program.

Untitled (18).png

Inheritance using Prototype or Prototypal Inheritance

Prototypal Inheritance is a feature in javascript used to add methods and properties of one object to another. It is a method by which an object can inherit the properties and methods of another object.

proto3.png

Untitled (20).png

We can also use

userDetails.__proto__ = userName;
userDetails.prototype = userName;