2022-02-20

Object Oriented Programming in JavaScript

Introduction

In this article, I explain objects, prototypes, and classes, crucial elements that shape the anatomy of Object-Oriented Programming (OOP) in JavaScript.

Objects in JavaScript

Objects in JavaScript are fundamental entities that can store collections of key-value pairs. The keys are typically strings (or symbols), and the values can be any valid JavaScript data type, including numbers, strings, booleans, functions, arrays, and other objects. They are powerful data structures that can represent complex, real-world phenomena within our code.

Creating Objects

Creating objects in JavaScript can be done in a few ways. The most common method is using object literals. An object literal is defined within curly braces {}.

js
let car = {
    make: "Tesla",
    model: "Model 3",
    color: "red",
    drive: function() {
        console.log("The car is driving");
    }
};

Another way is using the new Object() constructor.

js
let car = new Object();
car.make = "Tesla";
car.model = "Model 3";
car.color = "red";
car.drive = function() {
    console.log("The car is driving");
};

Object Properties and Methods

In JavaScript objects, the keys are known as properties and the values as their corresponding property values. If the property value is a function, we often refer to it as a method. Properties can be accessed and modified using the dot notation or bracket notation.

js
// Accessing properties
console.log(car.make);  // Output: "Tesla"
console.log(car["color"]);  // Output: "red"

// Modifying properties
car.make = "BMW";
car["color"] = "blue";

// Calling methods
car.drive();  // Output: "The car is driving"

Objects and References

In JavaScript, objects are reference types, meaning that when we assign an object to a new variable, we're not creating a new copy of the object, but rather creating a new reference to the same object.

js
let car1 = car;
car1.model = "Model S";
console.log(car.model);  // Output: "Model S"

Even though we changed car1.model, car.model also changed because they both point to the same object.

Built-in Objects

JavaScript provides a rich set of built-in objects, such as Array, Date, and Math, that offer various functionalities. These objects have properties and methods that can be used to manipulate the data they hold or to perform complex operations.

js
let now = new Date();
console.log(now.getFullYear());  // Output: The current year

let numbers = [1, 2, 3];
console.log(numbers.length);  // Output: 3

console.log(Math.sqrt(16));  // Output: 4

Prototypes in JavaScript

Every object in JavaScript has a hidden property called a prototype, which is another object that it "inherits" properties and methods from. This prototype object itself has a prototype of its own, forming a chain until we reach an object with a null prototype, which is the end of the prototype chain.

Prototype-based Inheritance

In JavaScript, inheritance is achieved through prototypes. When we try to access a property or a method on an object, JavaScript will first check the object itself. If it cannot find it there, it will look up the prototype chain until it finds the requested property or until it reaches the end of the chain.

Here's an example:

js
let vehicle = {
    wheels: 4,
    start: function() {
        console.log("The engine is starting");
    }
};

let car = Object.create(vehicle);
console.log(car.wheels);  // Output: 4
car.start();  // Output: "The engine is starting"

In this case, car doesn't have wheels property or start method of its own. But it can access these properties and methods through its prototype, vehicle.

Prototype Chain

The prototype chain is a term that refers to the chain of objects linked through the prototype property. The chain starts from a specific object, moves up to its prototype, and continues up the prototypes until it reaches null.

js
let vehicle = {
    wheels: 4
};

let car = Object.create(vehicle);
car.make = "Tesla";

let myCar = Object.create(car);
myCar.owner = "John Doe";

console.log(myCar.wheels);  // Output: 4
console.log(myCar.make);  // Output: "Tesla"
console.log(myCar.owner);  // Output: "John Doe"

In this case, myCar object inherits properties from car and vehicle through the prototype chain.

Proto Property

The prototype of an object can be accessed via the __proto__ property. This property is not recommended for use in production code because it is not supported in all JavaScript environments and has been deprecated in favor of Object.getPrototypeOf().

js
console.log(car.__proto__ === vehicle);  // Output: true
console.log(Object.getPrototypeOf(car) === vehicle);  // Output: true

Built-in Prototypes

Built-in JavaScript constructors like Array, Object, Function, and others have prototypes that include methods and properties relevant to their instances. For example, Array.prototype includes methods like push(), pop(), map(), filter(), and many others.

js
let arr = [1, 2, 3];
console.log(arr.__proto__ === Array.prototype);  // Output: true

Classes in JavaScript

In JavaScript, classes are a type of function introduced in ES6 to offer a more traditional-looking way of defining constructor functions and prototype methods. They provide a clean and elegant syntax for creating objects and dealing with inheritance.

Creating Classes

To define a class, we use the class keyword followed by the name of the class. Inside the class, we can define a constructor function, which is a special method for creating and initializing objects created with that class.

js
class Car {
    constructor(make, model) {
        this.make = make;
        this.model = model;
    }
    startEngine() {
        console.log(`${this.make} ${this.model}'s engine is starting`);
    }
}

let myCar = new Car("Tesla", "Model 3");
myCar.startEngine();  // Output: "Tesla Model 3's engine is starting"

Class Inheritance

Inheritance can be implemented in classes using the extends keyword. A class created with extends inherits all the methods from the parent class.

js
class ElectricCar extends Car {
    constructor(make, model, batteryCapacity) {
        super(make, model);
        this.batteryCapacity = batteryCapacity;
    }
    chargeBattery() {
        console.log(`${this.make} ${this.model}'s battery is charging`);
    }
}

let myElectricCar = new ElectricCar("Tesla", "Model S", 100);
myElectricCar.startEngine();  // Output: "Tesla Model S's engine is starting"
myElectricCar.chargeBattery();  // Output: "Tesla Model S's battery is charging"

Private and Public Class Fields

By default, all properties and methods in a JavaScript class are public. However, ES2020 introduced a way to create private class fields using a hash # prefix.

js
class Car {
    #speed = 0;
    accelerate() {
        this.#speed += 10;
        console.log(`Speed: ${this.#speed}`);
    }
}

let myCar = new Car();
myCar.accelerate();  // Output: "Speed: 10"
console.log(myCar.#speed);  // Throws an error: Property '#speed' is private and only accessible within class 'Car'.

Static Methods and Properties

Static methods and properties are those that belong to the class itself, not an instance of the class. You can declare a static method or property using the static keyword.

js
class Car {
    static numberOfWheels = 4;
    static displayNumberOfWheels() {
        console.log(`A car typically has ${this.numberOfWheels} wheels`);
    }
}

Car.displayNumberOfWheels();  // Output: "A car typically has 4 wheels"

Ryusei Kakujo

researchgatelinkedingithub

Focusing on data science for mobility

Bench Press 100kg!