A Beginner’s Guide to OOP in JavaScript


The Object-Oriented Programming (OOP) paradigm has played a key role in software development for many years. JavaScript is a language that performs this paradigm, implementing OOP in a manner that sets it apart from other languages. If you’re new to programming or OOP, it could be tricky. This guide will take you through a step-by-step approach to explain how OOP works in JavaScript and provide examples of its use cases. By the end, you’ll have grasped the fundamentals of OOP in JavaScript and can begin using it.

What is Object Oriented Programming?

Object-Oriented Programming is a method of writing programs that make it easier to manage and organize. Instead of writing code in a long and confusing block, OOP allows us to break down code into smaller, more manageable parts called objects. These objects can store data and instructions for what to do with that data, making it easier to reuse the code and keep track of what’s going on with it.

Objects are basic data units used to store and manipulate data. Objects are defined by their properties, which are the characteristics that describe the object. In JavaScript, an object’s property is represented as key-value pair. The key is a string that represents the name of a property, while the value is the data stored in that property. Remember that an object can store several data types, such as strings, numbers, and even other objects.

To create an object in JavaScript, we first create a variable with curly brackets.

const person = {};

Then we assign key-value pairs to the object.

const person = {
  name: "Bruce Wayne",
  age: 30,
  occupation: "Private Investigator",
};

In our person object, the name, age, and occupation keywords are the object’s properties (keys), while the values assigned to them are the property’s values.

Accessing Objects

This is a process of retrieving the data stored in an object. This is done by referencing the key attribute of an object. When we do so, we can access the value stored in that property. To perform this, we use one of the following notations.

  • The Dot Notation: To access the property or method of an object using this notation, we write the object name, then a dot (.), and then the property we want to access. Using our person object as an example, let’s access the name property.
person.name;

Logging this to the console gives the value stored in the name property.

  • The Bracket Notation: To access the property or method of an object using this notation, we write the object name, then a pair of square brackets ([ ]), and the property we want to access in quotes.
person["name"];

Logging this to the console yields the same result as the Dot Notation.

Constructor Functions

These are special functions that can be used to create objects. They are used to create multiple instances of the same object with the same properties and methods. To create a constructor function, we use the following syntax. First, we create a regular function and pass in parameters.

const Person = function (name, age) {

};

Next, we call our function with the new keyword. The new keyword enables our function to become a constructor function.

const person1 = new Person("James Bond", 40);

This creates an instance of the Person object and stores it in person1. This process also sets the this keyword on each instance we create. Keep in mind that the this keyword points to the newly created object being constructed. Next, we fill our newly created object with the parameters we passed when we created it.

const Person = function (name, age) {
  this.name = name;
  this.age = age;
};

Logging the person1 instance to the console now yields;

And with that, we’ve created our first object using a constructor function!

Adding methods to Constructor Functions

To add a method to a constructor function, we define that method in the constructor function. This way, all instance objects inherit that method when they’re created. For example, let’s add a method to our old constructor function.

const Person = function (name, age) {
  this.name = name;
  this.age = age;
  this.calcBirthYear = function () {
    return 2023 - this.age;
  };
};

To get the result of this method, we call the calcBirthYear method on our instance using the DOT notation.

person1.calcBirthYear();

Logging this to the console gives

There is yet a problem with this procedure. Each time we create an instance object, that object contains the calcBirthYear method, which can affect our code's performance.

The “this” Keyword

The this keyword in JavaScript refers to an object executing a function. It indicates which object executes the method and represents the object to which it belongs. Using the DOT notation, we can use the this keyword to refer to properties and methods of objects within those objects. It's critical to understand that the value of this is not constant and can change depending on how the function is called.

Session Replay for Developers

Uncover frustrations, understand bugs and fix slowdowns like never before with OpenReplay— an open-source session replay suite for developers. It can be self-hosted in minutes, giving you complete control over your customer data

Happy debugging! Try using OpenReplay today.

Prototypal Inheritance

Prototypal inheritance is a mechanism that allows objects to inherit properties and methods from other objects. This means you can create new objects that share common properties and methods with existing objects. This makes creating new objects and reusing code easier since you can build on existing objects instead of writing new code from scratch for each new object.

How Prototypal Inheritance works

In JavaScript, every object has a prototype, a blueprint object used to create objects.

  1. An object’s prototype can be accessed using the __proto__ property.

  2. The prototype object allows other objects to inherit its properties and methods.

  3. When you try to access a property or method in an object, JavaScript first checks if it exists on the object itself. If it doesn’t, it checks the object’s prototype. If it still doesn’t exist, it checks the object’s prototype’s prototype. This connection of objects by prototype is called the prototype chain. This process continues until the property or method is found or the end of the prototype chain is reached.

Sharing methods with Prototypal Inheritance

First, we recall our Person constructor function.

const Person = function (name, age) {
  this.name = name;
  this.age = age;
};

Next, we use the prototype property to add a method to our person object.

Person.prototype.calcBirthYear = function () {
   return 2023 - this.age;
 };

The prototype property lets us add methods to the prototype of a constructor function and not the constructor function itself. This way, instances created from a constructor function do not contain the methods but can inherit them from their constructor function's prototype. Taking a look at the constructor function on the console gives;

As we can see, our calcBirthYear method does not exist in the constructor function. But logging the prototype of our constructor function yields a different result.

console. log ( Person . prototype );

Our method exists in the constructor function’s prototype and can be inherited by instances of the constructor function.

Classes

Classes allow developers to create objects with specific properties and methods and act as a blueprint for creating objects with common characteristics. To create a class in JavaScript, we use the class keyword to declare a variable.

class PersonCl {};

Next, we specify a constructor function and pass in our parameters. This constructor function works the same way as the constructor function we’ve gone over previously.

class PersonCl {
  constructor(name, age) {
    this.name = name;
    this.age = age;
  }
}

To create an object from the PersonCl class, we call our new object with the new keyword.

Logging it to the console gives

Inheriting methods from Classes

Like in prototypal inheritance, objects can inherit methods from their parent class. To illustrate this, we create a method in our PersonCl class.

class PersonCl {
  constructor(name, age) {
    this.name = name;
    this.age = age;
  }
  calcBirthYear() {
    return 2023 - this.age;
  }
}

Then we pass that method to our instance object and log it to the console.

console.log(bruce.calcBirthYear());

It is important to note that when an object inherits a method from a class, that method does not exist on the object but on the prototype of that object. For further clarity, observe the image below.

As shown above, the calcBirthYear function does not exist in the object we created but exists in the prototype of that object.

Conclusion

In conclusion, OOP is a fascinating topic that can take your JavaScript skills to the next level. From understanding objects and constructor functions to grasping the this keyword and prototypal inheritance, this guide has covered all the essential elements of OOP. Let's not forget the elegance of using classes in JavaScript, which allows you to inherit methods and write more efficient and organized code. So what are you waiting for? Grab your code editor, your favorite cup of coffee, and start using OOP in your projects!


Originally published at blog.openreplay.com.