JavaScript Part 8: Object-Oriented Programming In JavaScript (Classes and Objects)

JavaScript Part 8: Object-Oriented Programming In JavaScript (Classes and Objects)


Please Subscribe Youtube| Like Facebook | Follow Twitter

Object-Oriented Programming In JavaScript

In this article, we will provide a detailed overview of Object-Oriented Programming In JavaScript (Classes and Objects) and provide examples of how they are used in JavaScript programming.

In the world of web development, JavaScript plays a crucial role in creating dynamic and interactive websites. One of the essential paradigms in JavaScript is Object-Oriented Programming (OOP). OOP allows developers to structure their code in a modular and organized manner, leading to more maintainable and scalable applications. In this article, we will delve into the core concepts of OOP in JavaScript, explore its advantages, and provide detailed examples with output to demonstrate its practical implementation.

Object-Oriented Programming revolves around the idea of creating reusable and self-contained building blocks called objects. These objects encapsulate both data (properties) and behavior (methods), allowing developers to model real-world entities and solve complex problems efficiently. JavaScript, being a versatile and flexible language, supports OOP concepts through prototypal inheritance.

The Pillars of Object-Oriented Programming

OOP is built upon three key pillars in JavaScript: encapsulation, inheritance and polymorphism.

Encapsulation

Encapsulation involves bundling data and methods together within a class. It allows us to control access to the internal state of an object, ensuring that data is accessed and modified only through defined methods. Encapsulation promotes data integrity and hides the implementation details of an object, making the code more maintainable and modular.

Inheritance

Inheritance is a mechanism that allows a class to inherit properties and methods from a parent class. It enables code reuse by creating a hierarchy of classes where child classes inherit the characteristics of their parent class. Child classes can extend the functionality of the parent class by adding new methods or overriding existing ones. Inheritance promotes code reusability and facilitates the creation of specialized classes based on common attributes and behaviors.

Polymorphism

Polymorphism allows objects of different classes to be treated as objects of a common superclass. It enables the use of a single interface to represent multiple types, providing flexibility and extensibility in code. Polymorphism allows for method overriding, where a subclass can provide its own implementation of a method defined in its superclass. This allows objects of different classes to exhibit different behaviors while still adhering to a common interface.

JavaScript does not have built-in support for abstract classes or interfaces like some other object-oriented languages.

We will explain them further in detail in next article. In this article we will explain Classes and Objects

Classes and Objects

In JavaScript, objects can be created in two ways: using object literals or classes. Object literals provide a straightforward way to define an object and its properties in a single line. In JavaScript, an object is a data structure that allows you to store and organize data as key-value pairs. It is a fundamental concept in JavaScript and provides a way to represent and manipulate complex data.

For instance:

const car = {
  brand: "Tesla",
  model: "Model 3",
  year: 2022,
  startEngine() {
    console.log("Engine started!");
  }
};

In the example above, we define an object called person with three properties: brand, model, and year. The properties are assigned values using the colon (:) notation, separating the key (property name) from the value.

On the other hand, classes offer a more structured and organized approach to object creation. A class is a blueprint for creating objects with predefined properties and methods. Here’s an example of defining a class in JavaScript:

class Car {
  constructor(brand, model, year) {
    this.brand = brand;
    this.model = model;
    this.year = year;
  }

  startEngine() {
    console.log("Engine started!");
  }
}

const myCar = new Car("Tesla", "Model 3", 2022);

In this example, we define a Car class with a constructor method that takes in the brand, model, and year as parameters and assigns them to the respective properties of the class instance. The startEngine method is defined within the class to simulate starting the car’s engine. We then create an instance of the Car class using the new keyword.

Methods, Fields and Constructors

Methods are functions defined within a class that perform specific tasks or actions. Fields, also known as instance variables, hold the state or data associated with objects.

In JavaScript, you can access methods and fields using the dot notation. The dot notation allows you to access members (methods and fields) of a class or object.

To access a method, you use the following syntax:

objectName.methodName(arguments);

To access a field, you use the following syntax:

objectName.fieldName;
Or
objectName["fieldName"];

In JavaScript, objects are dynamic, which means you can add, modify, or delete properties at any time. For example:

myCar.age = 26; // Adding a new property
myCar.year = 2023; // Modifying an existing property
delete myCar.model; // Deleting a property

console.log(model); // Output: { brand : "Tesla", year: 2023, age: 26 }

Constructors are special methods used to initialize objects. They allow you to set initial values for an object’s properties. In JavaScript, constructors are special methods that are defined within a class and have the same name as the class itself. This allows the constructor to be automatically invoked when an object is created using the new keyword.

There are two main types of constructors in JavaScript: no-argument constructors and parameterized constructors.

No-Argument/Non-Parameterized Constructors

A no-argument constructor, also known as a default constructor, does not take any parameters. It initializes the object with default values or performs basic initialization tasks.

class Car {
  constructor() {
    // Initialization code or default values
  }
}

const myCar = new Car(); // Creating an object with a non-argument constructor

Parameterized Constructors

Parameterized constructors are constructors that accept one or more parameters. They allow you to initialize the object with specific values provided during object creation. These values are passed as arguments to the constructor and used to set the initial state of the object.

class Car {
  constructor(make, model, year) {
    this.make = make;
    this.model = model;
    this.year = year;
  }
}

const myCar = new Car("Toyota", "Camry", 2022); // Creating an object with a parameterized constructor

this keyword

The this keyword refers to the current instance of an object or the object on which a method is being called. It provides a way to access and manipulate the properties and methods of the current object.

i.e

this.model = model; 

This line assigns the value of the make parameter to the make attribute of the current object. The use of this is necessary when there is a naming conflict between the parameter and the attribute. It explicitly refers to the instance variable make of the current object, distinguishing it from the method parameter.

Example

class Car {
  constructor(make, model, year) {
    this.make = make;
    this.model = model;
    this.year = year;
  }

  // Getter methods
  getMake() {
    return this.make;
  }

  getModel() {
    return this.model;
  }

  getYear() {
    return this.year;
  }

  // Setter methods
  setMake(make) {
    this.make = make;
  }

  setModel(model) {
    this.model = model;
  }

  setYear(year) {
    this.year = year;
  }

  // Other methods
  startEngine() {
    console.log("Engine started!");
  }

  stopEngine() {
    console.log("Engine stopped!");
  }

  carDetails() {
    console.log(`make: ${this.make}, model: ${this.model}, year: ${this.year}`);
  }
}

const myCar = new Car("Toyota", "Camry", 2022);
console.log(myCar.getMake());   // Output: "Toyota"
console.log(myCar.getModel());  // Output: "Camry"
console.log(myCar.getYear());   // Output: 2022

myCar.setMake("Honda");
myCar.setModel("Accord");
myCar.setYear(2023);

console.log(myCar.getMake());   // Output: "Honda"
console.log(myCar.getModel());  // Output: "Accord"
console.log(myCar.getYear());   // Output: 2023

myCar.startEngine();            // Output: "Engine started!"
myCar.carDetails();             // Output: "make: Honda, model: Accord, year: 2023"

Output

Toyota
Camry
2022
Honda
Accord
2023
Engine started!
make: Honda, model: Accord, year: 2023

The code defines a Car class in JavaScript. It has a constructor that takes make, model, and year as parameters and initializes the corresponding properties of the Car object.

Getter methods (getMake(), getModel(), getYear()) are used to retrieve the values of the make, model, and year properties.

Setter methods (setMake(), setModel(), setYear()) are used to update the values of the make, model, and year properties.

Other methods like startEngine(), stopEngine(), and carDetails() perform specific actions related to the Car object.

The code creates an instance of the Car class named myCar with the initial values “Toyota”, “Camry”, and 2022. It then retrieves and prints the values of the make, model, and year properties using the respective getter methods.

Next, the setter methods are used to update the values of the make, model, and year properties to “Honda”, “Accord”, and 2023 respectively. The updated values are then retrieved and printed using the getter methods.

Finally, the startEngine() method is called to print “Engine started!” to the console, and the carDetails() method is called to print the details of the car (make, model, and year) to the console.

Object Conversion

To convert a string to an object in JavaScript, you can use the JSON.parse() method. This method parses a JSON-formatted string and returns the corresponding JavaScript object.

const jsonString = '{"name": "John", "age": 25, "city": "New York"}';
const obj = JSON.parse(jsonString);

console.log(obj.name); // Output: John
console.log(obj.age); // Output: 25
console.log(obj.city); // Output: New York

In the example above, the JSON.parse() method is used to convert the jsonString into a JavaScript object called obj. We can then access the properties of the object using dot notation.

Conversely, to convert an object to a string, you can use the JSON.stringify() method. This method converts a JavaScript object to a JSON-formatted string.

const obj = {
  name: "John",
  age: 25,
  city: "New York"
};

const jsonString = JSON.stringify(obj);

console.log(jsonString); // Output: {"name":"John","age":25,"city":"New York"}

In the example above, the JSON.stringify() method is used to convert the obj object into a JSON-formatted string called jsonString.

Both JSON.parse() and JSON.stringify() are part of the JSON object, which is built into JavaScript. They provide a convenient way to convert between string and object representations.

Traversing an object in JavaScript

Here are a few common methods to traverse an object

For…in loop

You can use a for…in loop to iterate over the properties of an object. This loop iterates over all enumerable properties of an object, including those inherited from its prototype chain.

const obj = { a: 1, b: 2, c: 3 };

for (let key in obj) {
  console.log(key + ": " + obj[key]);
}

In the example above, the for…in loop iterates over the properties (a, b, and c) of the obj object and logs their keys and values.

Object.keys()

The Object.keys() method returns an array containing the enumerable property names of an object. You can then iterate over this array to access the object’s properties.

const obj = { a: 1, b: 2, c: 3 };

Object.keys(obj).forEach(key => {
  console.log(key + ": " + obj[key]);
});

In the example above, Object.keys(obj) returns an array of property names ([“a”, “b”, “c”]). We use forEach() to iterate over this array and log the key-value pairs of the obj object.

Object.entries()

The Object.entries() method returns an array containing arrays of key-value pairs of the object’s enumerable properties. You can iterate over these arrays to access both the keys and values.

const obj = { a: 1, b: 2, c: 3 };

Object.entries(obj).forEach(([key, value]) => {
  console.log(key + ": " + value);
});

In the example above, Object.entries(obj) returns an array of key-value pairs ([[“a”, 1], [“b”, 2], [“c”, 3]]). We use forEach() to iterate over these arrays and log the key-value pairs of the obj object.

Static Method And Non-Static Method in JavaScript

Non-Static Methods

Non-static methods are associated with instances of a class. They are defined on the prototype of the class and are accessible through instances of the class. Non-static methods have access to instance-specific data (properties) and can modify the state of the object. To define a non-static method, you add the method to the class prototype using the ClassName.prototype.methodName syntax.

class Car {
  constructor(make, model) {
    this.make = make;
    this.model = model;
  }

  // Non-static method
  startEngine() {
    console.log("Engine started!");
  }

  // Non-static method
  getCarDetails() {
    console.log(`Make: ${this.make}, Model: ${this.model}`);
  }
}

const myCar = new Car("Toyota", "Camry");
myCar.startEngine();        // Call a non-static method on an instance
myCar.getCarDetails();      // Call another non-static method on the same instance

Output

Engine started!
Make: Toyota, Model: Camry

Static Methods

Static methods belong to the class itself, rather than instances of the class. They are defined directly on the class and can be accessed without creating an instance of the class. Static methods do not have access to instance-specific data (properties) and cannot modify the state of the object. To define a static method, you use the static keyword before the method definition.

class MathUtils {
  static square(number) {
    return number * number;
  }

  static sum(numbers) {
    return numbers.reduce((acc, curr) => acc + curr, 0);
  }
}

console.log(MathUtils.square(5));    // Call a static method directly on the class
console.log(MathUtils.sum([1, 2, 3]));  // Call another static method directly on the class

Output

25
6

Differences between static and non-static methods in JavaScript

TermStatic MethodNon-Static Method
DefinitionDefined on the class itselfDefined on the class prototype
AccessAccessed directly on the classAccessed through instances of the class
InvocationClassName.methodName()instance.methodName()
Instance-SpecificCannot access instance-specific data (this)Can access instance-specific data (this)
State ModificationCannot modify the state of the objectCan modify the state of the object
InheritanceInherited by child classesInherited by child classes
UtilityUseful for functionality not tied to instancesUseful for behavior specific to individual instances

Conclusion

In JavaScript, classes and objects are essential components of object-oriented programming (OOP). They provide a way to structure and organize code, resembling real-world entities and their interactions. By encapsulating data and behavior within classes, we can create objects that represent specific instances of those classes.

Classes serve as blueprints or templates, defining the attributes (data) and methods (behavior) that objects of that class will possess. Objects, on the other hand, are instances of classes that have their own unique state and behavior.

JavaScript Beginner Tutorial Series

Please Subscribe Youtube| Like Facebook | Follow Twitter


Leave a Reply

Your email address will not be published. Required fields are marked *