Mastering Object-Oriented Programming in JavaScript
Object-Oriented Programming (OOP) is a powerful programming paradigm that focuses on organizing code into reusable and logical components called objects. JavaScript, while not classically object-oriented like Java or C++, supports OOP through prototypes and more recently through classes (ES6+ syntax).
This module will guide you through OOP in JavaScript — from prototypes to ES6 classes — and help you understand concepts like inheritance, encapsulation, and polymorphism.
Table of Contents
- What is Object-Oriented Programming?
- JavaScript’s Prototype-Based Inheritance
- Constructor Functions
- The prototypeProperty
- ES6 Classes
- Inheritance with Classes
- Getters and Setters
- Static Methods
- Encapsulation and Private Fields
- Conclusion
1. What is Object-Oriented Programming?
OOP is a paradigm where you model code using real-world objects. Objects have:
- Properties (data/state)
- Methods (behavior)
Core OOP principles:
- Encapsulation: Wrapping data and behavior in a single unit (object).
- Inheritance: Creating new objects from existing ones.
- Polymorphism: Ability to call the same method on different objects.
- Abstraction: Hiding complexity behind simple interfaces.
2. JavaScript’s Prototype-Based Inheritance
JavaScript uses prototypes instead of classical inheritance. Every object in JS has an internal [[Prototype]], which links to another object. This is how inheritance works.
const person = {
  greet: function() {
    console.log("Hello");
  }
};
const student = Object.create(person);
student.study = function() {
  console.log("Studying...");
};
student.greet();  // Inherited from person
student.study();  // Own method
3. Constructor Functions
Before ES6 classes, JavaScript used constructor functions to create objects:
function Person(name, age) {
  this.name = name;
  this.age = age;
}
Person.prototype.greet = function() {
  console.log(`Hi, I'm ${this.name}`);
};
const john = new Person("John", 30);
john.greet(); // Hi, I'm John
Here, Person is a constructor, and .greet is shared via the prototype.
4. The prototype Property
Every function in JS has a .prototype object that allows you to attach shared methods:
function Animal(name) {
  this.name = name;
}
Animal.prototype.speak = function() {
  console.log(`${this.name} makes a sound`);
};
All instances of Animal share the same .speak() method — this is efficient and avoids duplicating functions.
5. ES6 Classes
ES6 introduced the class keyword to make OOP more readable and similar to traditional languages.
class Person {
  constructor(name, age) {
    this.name = name;
    this.age = age;
  }
  greet() {
    console.log(`Hi, I'm ${this.name}`);
  }
}
const alice = new Person("Alice", 25);
alice.greet(); // Hi, I'm Alice
Under the hood, JavaScript classes still use prototypes — class is syntactic sugar over prototype-based inheritance.
6. Inheritance with Classes
Classes support extends for inheritance:
class Animal {
  constructor(name) {
    this.name = name;
  }
  speak() {
    console.log(`${this.name} makes a sound`);
  }
}
class Dog extends Animal {
  speak() {
    console.log(`${this.name} barks`);
  }
}
const dog = new Dog("Buddy");
dog.speak(); // Buddy barks
The Dog class inherits from Animal and overrides the speak method.
7. Getters and Setters
Getters and setters let you define methods that behave like properties:
class Circle {
  constructor(radius) {
    this._radius = radius;
  }
  get area() {
    return Math.PI * this._radius ** 2;
  }
  set radius(value) {
    if (value > 0) this._radius = value;
  }
}
const c = new Circle(10);
console.log(c.area); // 314.159...
8. Static Methods
static methods belong to the class, not to instances:
class MathUtil {
  static add(x, y) {
    return x + y;
  }
}
console.log(MathUtil.add(5, 3)); // 8
Useful for utility methods that don’t rely on instance data.
9. Encapsulation and Private Fields
Modern JavaScript supports private fields using the # syntax:
class Counter {
  #count = 0;
  increment() {
    this.#count++;
  }
  get value() {
    return this.#count;
  }
}
const counter = new Counter();
counter.increment();
console.log(counter.value); // 1
// console.log(counter.#count); ❌ SyntaxError
Encapsulation hides internal implementation details and protects state.
10. Conclusion
Object-Oriented JavaScript enables you to write cleaner, modular, and more scalable code. With both prototype-based and class-based styles, JavaScript provides flexibility in how you design your applications.
You now know how to:
- Use constructor functions and prototypes
- Create ES6 classes and extend them
- Apply OOP principles like encapsulation and inheritance
- Use private fields, static methods, and getters/setters
In the next module, we’ll return to the browser and explore the DOM (Document Object Model) in depth.

