Object-Oriented JavaScript (OOP in JS)

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

  1. What is Object-Oriented Programming?
  2. JavaScript’s Prototype-Based Inheritance
  3. Constructor Functions
  4. The prototype Property
  5. ES6 Classes
  6. Inheritance with Classes
  7. Getters and Setters
  8. Static Methods
  9. Encapsulation and Private Fields
  10. 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.