JavaScript Prototype Introduction - Programming Paradigms

What is JavaScript Prototype?

December 20, 2024

Today, I want to review one of the most important concepts in JS, which is the prototype, but I think it's better to start with the basic, let's review the programming language paradigms first.

What is so-called programming language paradigms?

Think of a tool box, you have a hammer, a screwdriver, a saw, etc. Each tool has its own purpose, and you can solve different problems with different tools, sometime you need to combine them to solve a complex problem, this idea is similar to programming language paradigms.

Programming paradigms are fundamental approaches or styles of programming, it defines the way of thinking and solving problems.

Here are some common programming paradigms and its characteristics:

JavaScript wears multiple hats

JavaScript is a multi-paradigm programming language, it supports OOP concepts, it treats functions as first-class citizens, it can be used in an imperative style or a declarative style.

Let's say we want to filter out the odd numbers from an array, and multiply each number by 2, and then sum them up.

Imperative style

const numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
 
function imperativeApproach(arr: number[]) {
  let result = 0;
  for (let i = 0; i < arr.length; i++) {
    if (arr[i] % 2 === 0) {
      result += arr[i] * 2;
    }
  }
  return result;
}
 
console.log(imperativeApproach(numbers));

Declarative style

const numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
 
function declarativeApproach(arr: number[]) {
  return arr
    .filter((num) => num % 2 === 0)
    .map((num) => num * 2)
    .reduce(acc, (curr) => acc + curr, 0);
}
 
console.log(declarativeApproach(numbers));

Functional style

const numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
 
const isEven = (num: number) => num % 2 === 0;
const multiplyByTwo = (num: number) => num * 2;
const sum = (acc: number, curr: number) => acc + curr;
 
function functionalApproach(arr: number[]) {
  return arr.filter(isEven).map(multiplyByTwo).reduce(sum, 0);
}
 
console.log(functionalApproach(numbers));

Object-Oriented style

const numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
 
class NumberProcessor {
  constructor(private numbers: number[]) {}
 
  isEven(num: number) {
    return num % 2 === 0;
  }
 
  multiplyByTwo(num: number) {
    return num * 2;
  }
 
  sum(acc: number, curr: number) {
    return acc + curr;
  }
 
  process() {
    return this.numbers.filter(this.isEven).map(this.multiplyByTwo).reduce(this.sum, 0);
  }
}
 
const processor = new NumberProcessor(numbers);

Prototype in JavaScript

In OOP, there're two ways to create objects: class-based and prototype-based.

Class-based OOP

It is more traditional, more intuitive, think of a blueprint, you can create multiple instances from the blueprint.

class Enemy() {
  constructor(name) {
    this.name = name;
  }
 
  attack() {
    console.log(`${this.name} is attacking!`);
  }
 
  defend() {
    console.log(`${this.name} is defending!`);
  }
}
 
const enemy1 = new Enemy("Goblin");
const enemy2 = new Enemy("Orc");
 
enemy1.attack(); // Goblin is attacking!
enemy2.defend(); // Orc is defending!

Prototype-based OOP

It is more flexible, it allows you to create objects without a blueprint, simply by cloning an existing object.

const enemy = {
  attack() {
    console.log(`${this.name} is attacking!`);
  },
 
  defend() {
    console.log(`${this.name} is defending!`);
  },
};
 
const enemy1 = Object.create(enemy);
enemy1.name = "Goblin";
enemy1.attack(); // Goblin is attacking!
 
const enemy2 = Object.create(enemy);
enemy2.name = "Orc";
enemy2.defend(); // Orc is defending!

Summary

In this article, we've reviewed the programming language paradigms, and how JavaScript supports multiple paradigms, and we've learned the difference between class-based OOP and prototype-based OOP.

Back to Blog 🏃🏽‍♀️