Object-Oriented Programming in JavaScript uses classes as blueprints for creating objects that bundle data and behavior together. This lesson covers defining classes with constructors and methods, creating instances with new, extending classes with inheritance and super(), and encapsulating internal state with private (#) fields.
1JS OOP / Classes | JavaScript Tutorial - In-Depth Guide Part 1
Object-Oriented Programming (OOP) is a way to organize code into ' 'Blueprints' called Classes. It helps model real-world entities.
// Modern OOP in JS2JS OOP / Classes | JavaScript Tutorial - In-Depth Guide Part 2
A Class is a template. We use the ' 'constructor' to initialize data when we create a new instance of the class.
class Hero {
constructor(name) {
this.name = name;
this.health = 100;
}
}3JS OOP / Classes | JavaScript Tutorial - In-Depth Guide Part 3
Methods are functions that belong to the class. They define what an object can ' 'do'.
class Hero {
// ...constructor
attack() {
console.log(`${this.name} strikes!`);
}
}4JS OOP / Classes | JavaScript Tutorial - In-Depth Guide Part 4
Inheritance: You can create specialized classes that ' 'extend' a parent class. They inherit all existing behaviors.
class Mage extends Hero {
castSpell() {
console.log('Fireball!');
}
}5JS OOP / Classes | JavaScript Tutorial - In-Depth Guide Part 5
If a child has a constructor, it MUST call super() first. This triggers the parent
class Mage extends Hero {
constructor(name, mana) {
super(name);
this.mana = mana;
}
}6JS OOP / Classes | JavaScript Tutorial - In-Depth Guide Part 6
Encapsulation: Use #' to create private fields. These cannot be touched or modified from outside the class.
class Bank {
#balance = 0;
show() { return this.#balance; }
}7JS OOP / Classes | JavaScript Tutorial - In-Depth Guide Part 7
Logic modeling: OOP allows you to group data and logic together, making your app easier to manage.
<h1>App: Structured</h1>8JS OOP / Classes | JavaScript Tutorial - In-Depth Guide Part 8
OOP foundations established! You can now build robust, reusable system architectures.
<h1>Architecture: Solid</h1>9JS OOP / Classes | JavaScript Tutorial - In-Depth Guide Part 9
Next, we master 'JS Modules' to organize your code into separate, manageable files.
<h1>Next: ES Modules</h1>10Step-by-Step Breakdown
Object-Oriented Programming (OOP) is a way to organize code into ' 'Blueprints' called Classes. It helps model real-world entities.
A Class is a template. We use the ' 'constructor' to initialize data when we create a new instance of the class.
Methods are functions that belong to the class. They define what an object can ' 'do'.
Checkpoint: Which keyword do you use to create a real object from a class blueprint?
- ācreate
- ānew
- āinit
Inheritance: You can create specialized classes that ' 'extend' a parent class. They inherit all existing behaviors.
If a child has a constructor, it MUST call super() first. This triggers the parent
Checkpoint: What happens if you forget to call super() in a child constructor that uses this'?
- āNothing, it works fine
- āJavaScript throws a ReferenceError
Encapsulation: Use #' to create private fields. These cannot be touched or modified from outside the class.
Logic modeling: OOP allows you to group data and logic together, making your app easier to manage.
Checkpoint: Can a private property (starting with #) be accessed directly from an instance object?
- āYes, objects are open
- āNo, it throws a SyntaxError
OOP foundations established! You can now build robust, reusable system architectures.
Next, we master 'JS Modules' to organize your code into separate, manageable files.
Level Up š
Advanced cheat sheets, SEO tricks, and interview prep for this topic.
Browser Support
Fully supported.
Fully supported.
Fully supported.
Fully supported.
Accessibility (A11y)
1A Class's render() Method Must Emit the ARIA State It Tracks Internally
When a UI component is modeled as a class (e.g. a custom Dropdown with an `#isOpen` private field), every state change must be reflected in the markup the class renders ā `aria-expanded`, `aria-selected`, and similar attributes need to be recomputed from the class's internal state on every render, not just the visual appearance.
SEO Implications
- 1
Class-Based Components Rendered Only on the Client Can Delay First Contentful Paint
If a page's main content is produced by instantiating classes and calling render() only after JavaScript loads and executes, crawlers and users relying on the initial HTML may see an empty page; server-side rendering or static generation ensures the meaningful content exists before any class logic runs.
Best Practices
Favor Composition Over Deep Inheritance Chains
A class hierarchy more than two or three levels deep (Animal -> Mammal -> Dog -> ServiceDog) becomes fragile and hard to reason about, since a change to a base class can ripple unpredictably through every descendant. Prefer composing smaller, focused classes or objects together over building long inheritance chains.
Use Private (#) Fields for Any State That Shouldn't Be Mutated Directly
Exposing internal state as a plain public property invites external code to set it to an invalid value and bypass any validation logic in your methods; a private field paired with a getter/setter method lets you control exactly how that state can be read or changed.
Frequent Bugs
Forgetting to call super() in a subclass constructor throws `ReferenceError: Must call super constructor before accessing 'this'`.
Any subclass that defines its own constructor must call `super(...)` before using `this` anywhere in that constructor ā this initializes the parent class's part of the instance first. If the subclass doesn't need custom constructor logic, omit the constructor entirely and it will inherit the parent's automatically.
A method loses its `this` binding when passed as a callback (e.g. to `addEventListener` or `setTimeout`), so `this` becomes undefined inside it.
Regular class methods aren't automatically bound to their instance. Either convert the method to an arrow function class field (`attack = () => { ... }`), or explicitly bind it in the constructor (`this.attack = this.attack.bind(this)`) before passing it around as a callback.
Real-World Examples
Modeling a Game Character Hierarchy with Inheritance
A browser game needed several character types (Warrior, Mage, Archer) that all shared core stats and a takeDamage() method, but each had a unique special ability. A base Character class held the shared logic, and each character type extended it, calling super() to inherit health and name handling.
class Character {
constructor(name, health) {
this.name = name;
this.health = health;
}
takeDamage(amount) {
this.health -= amount;
}
}
class Mage extends Character {
constructor(name) {
super(name, 80);
this.mana = 100;
}
castSpell() {
this.mana -= 20;
console.log(`${this.name} casts a spell!`);
}
}