Object Oriented Programming in JavaScript.

Introduction:

This is by no means an exhaustive guide to Object Oriented Programming in Javascript. These notes on OOP in JavaScript are what I mostly use, and come back to them daily for reference.

On this note, I primarily focus on creating objects with class and function keywords. I also talk about inheritance method chaining and some other stuff. For a detailed explanation and examples, please visit the MDN's blog here on classes.

Object Oriented Programming TLDR

Object Example

  • An Object in JavaScript is a collection of properties. Property can be functions (function has an action associated with it) or a simple key :value pair which could just represent a feature of the object it is in. For example: color: red is a property whereas function accelerate(){} is a property of the car that has some action associated with it.

    • For example,

const car = {
    color: red,
    type: sedan, 
    accelerate: function(){
        // code here
    }
}

Please Note: I have assigned the object above to a variable called car. If you don't need to refer back to the object, you don't need to assign the object to a variable.

Creating Objects: Object Literal

  • Also known as object initializers, object literals allow us to create Javascript objects. We need to use curly braces in JavaScript to initialize the object.
// empty object
let obj = {} 

// object with property and value
let user = {
    name: 'John Doe', // property can be identifies
    1000: 'example_1', // or property can be a number 
    "email": 'john.doe@useremail.com', // or it can be a string.     
    login: function(){} 
    logout(){} // ES6 syntax. 
}
  • In the user the object above, we have encapsulated or gathered all the relevant properties of a user in one place. Think of opening and closing curly braces {} as a capsule that groups all the relevant properties of user.

Accessing and Updating Properties

Accessing Object Properties
  • To access object properties we can use simple dot notation.

console.log(user.email) 
// expected output: john.doe@useremail.com
  • However, dot notation only works when the object has an identifier that starts with a letter, $, _ or unicode escape sequence. So, to access the property of type number you need to use the following syntax.

console.log(user[1000]) // expected output: example_1 

// this notation below works for other properties as well. 

console.log(user['email']) // expected output: john.doe@useremail.com
  • We can access the properties of objects dynamically as well.

let foo = 'email'
console.log(user[foo]) // expected output: john.doe@useremail.com
// changing the variable 
let foo = 'name'
console.log(user[foo]) // expected output: John Doe
Updating Object Properties
  • To update the property, simply get the property name and set it to new value. For example, for our user object, we can do the following.

user[1000] = "example_2"; 
user.email = "email@johndoe.com";
  • Setting a property that does not exist on the object:

user.race = 'South Asian' 
console.log(user) // expected output contains: {.... race: "South Asian"}

Class and Constructor Function: Creating Multiple Objects With the Same Property

  • You might have to create multiple objects with the same property types, just like creating multiple computers or cars with the same features (property).

  • First, create a constructor class (blueprint) of the object.

class Car {
    constructor(color, type, accelerateFn){
        this.color = color;
        this.type = type;
        this.accelerate = function(){console.log(accelerateFn)};
    }
}

this represents the object it is in. When we create a new object (example: whiteCar) with the blueprint above, this keyword will represent the object just created (whiteCar)

  • Also, there can only be one method with the name constructor inside the Class.

Now to create a new object with all these properties of the constructor class, do the following.

const whiteCar = new Car('white','hatchback','is a fast car')
console.log(whiteCar.color) // expected output: white

const redCar = new Car('red', 'sedan', 'is slower car')
console.log(redCar.color) // expected output: red
Methods:
  • For the example above: we can add methods brake and headlights like this

class Car {
    constructor(color, type, accelerateFn){
        this.color = color;
        this.type = type;
        this.accelerate = function(){console.log(accelerateFn)};
    }
    // methods
    brake(){
        console.log(`Brake of this ${this.color} ${this.type} is in            good condition.`)
          return this;
    }

    headLights(){
        console.log(`Lights of this ${this.color} ${this.type} is in        good condition.`)
          return this;
    }

}
  • If you want the methods or properties to not be shared with another object/instance created from the class, use the word static

class Car {
    constructor(color, type, accelerateFn){
        this.color = color;
        this.type = type;
        this.accelerate = function(){console.log(accelerateFn)};
    }
    // methods
    brake(){
        console.log(`Brake of this ${this.color} ${this.type} is in good condition.`)
          return this;
    }
    headLights(){
        console.log(`Lights of this ${this.color} ${this.type} is in good condition.`)
          return this;
    }
    // static example: 
    static moto = 'Let\'s make the world a better place'
    static hello(){
        console.log(`This method is only available in this Car Object`)
    }
}
Method Chaining.
  • return this in the above object, methods return the object it is in. What that allows us to do is call all the methods of the object after one another.
    For example,

const redCar = new Car('red','sedan','is faster')
console.log(redCar.brake().headLights())

Here, we can call headlights() after brake().

Class Inheritance

  • If you want to create a new object with all the properties of the previous one plus some more properties and methods of its own, you need to inherit the properties of the previous object with class Inheritance.

class SuperCar extends Car {
    launchMode(){
        console.log(`Launch Mode of ${this.color} supercar`)
    }
}
  • Now when you create a new SuperCar, you need to do this

const ferrari = new SuperCar('red','super-car','is fastest')

Note: The new object that extends on properties of another object expects all the arguments of the previous one. Therefore, in this example above, we need to provide in color, type and accelerateFn

Emulating Class with function Keyword

  • The following code with function keyword is also valid

function Car(color, type, accelerateFn){
    this.color = color;
    this.type = type;
    this.accelerate = function(){console.log(accelerateFn)};
}

// to attach methods, we can use prototype

Car.prototype.brake = function(){
    console.log(/*code here*/)
}

Now, an instance of the object can just call in the method


const ferrari = new SuperCar('red','super-car','is fastest') 
ferrari.brake();  // works. :)
Inheritance of class created with the function keyword
  • To create a new Object from the original object (with constructor function) created with function() keyword, do this.

function SuperCar(...args) {
    Car.apply(this, arg)
}
// here, ...args is taking arguments of Car and making them an array.

Now, you can create an object like this


new lambo = new SuperCar('red','superCar','is fastest') // with all the same args
  • To inherit the prototype methods attached to the original object created with function() keyword, use Object.create() like so.

SuperCar.prototype = Object.create(Car.prototype) // now all the prototype functions appear for SuperCar object as well.

Important Note:

  • An Important difference between funciton decleration and class decleration is that while functions can be called before they are defined but classes can't.

const ferrari = new SuperCar() 
class SuperCar = {}

// Refrence Error because we are calling function before creating it.

Did you find this article valuable?

Support Pratik Thapa by becoming a sponsor. Any amount is appreciated!