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
prototype
Property - 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.