This document explains the fundamental OOP concepts used throughout the design patterns examples.
A class is like a blueprint or template for creating objects. Think of it as a cookie cutter - it defines the shape and properties, but the actual cookies (objects) are created from it.
If you're building houses, a class is the architectural plan. The actual houses built from that plan are the objects (instances).
class Person {
constructor(name, age) {
this.name = name;
this.age = age;
}
introduce() {
console.log(`Hi, I'm ${this.name} and I'm ${this.age} years old`);
}
}
// Creating objects (instances) from the class
const person1 = new Person('Alice', 30);
const person2 = new Person('Bob', 25);
person1.introduce(); // Hi, I'm Alice and I'm 30 years old
person2.introduce(); // Hi, I'm Bob and I'm 25 years oldKey Points:
- Classes define properties (what the object has) - like
nameandage - Classes define methods (what the object can do) - like
introduce() - You create actual objects using the
newkeyword
A constructor is a special method that runs automatically when you create a new object from a class. It's used to set up the initial state of the object.
When you buy a new phone, the constructor is like the initial setup process - setting your language, wifi, and creating your profile. It happens once when the phone is "created."
class Car {
constructor(brand, model, year) {
// This code runs when you do: new Car(...)
this.brand = brand;
this.model = model;
this.year = year;
this.isRunning = false; // Default value
}
start() {
this.isRunning = true;
console.log(`${this.brand} ${this.model} is now running`);
}
}
const myCar = new Car('Toyota', 'Camry', 2023);
// Constructor runs automatically, setting:
// myCar.brand = 'Toyota'
// myCar.model = 'Camry'
// myCar.year = 2023
// myCar.isRunning = false
myCar.start(); // Toyota Camry is now runningKey Points:
- Constructor is always named
constructor - It runs automatically when you use
new - It sets up the object's initial properties
- Each class can have only one constructor
this is a special keyword that refers to the current object. It's like saying "this specific instance" or "myself."
Imagine you're in a classroom full of students. When the teacher says "raise your hand," each student thinks "my hand" (not someone else's). this is like "my" - it refers to the specific object being used.
class BankAccount {
constructor(owner, balance) {
this.owner = owner; // THIS account's owner
this.balance = balance; // THIS account's balance
}
deposit(amount) {
this.balance += amount; // Add to THIS account's balance
console.log(`${this.owner}'s new balance: $${this.balance}`);
}
withdraw(amount) {
this.balance -= amount; // Subtract from THIS account's balance
console.log(`${this.owner}'s new balance: $${this.balance}`);
}
}
const account1 = new BankAccount('Alice', 1000);
const account2 = new BankAccount('Bob', 500);
account1.deposit(200);
// Inside deposit(), 'this' refers to account1
// Output: Alice's new balance: $1200
account2.deposit(100);
// Inside deposit(), 'this' refers to account2
// Output: Bob's new balance: $600Key Points:
thisrefers to the object that's currently executing the codethis.propertyaccesses a property of the current objectthis.method()calls a method on the current object- Different objects have different
thiscontexts
class Counter {
constructor() {
this.count = 0; // Initialize THIS counter's count
}
increment() {
this.count++; // Increment THIS counter's count
}
getCount() {
return this.count; // Return THIS counter's count
}
}
const counter1 = new Counter();
const counter2 = new Counter();
counter1.increment();
counter1.increment();
console.log(counter1.getCount()); // 2 (counter1's count)
counter2.increment();
console.log(counter2.getCount()); // 1 (counter2's count)super() is like calling your parent to help you set up before you do your own setup. In programming terms, it calls the constructor of the parent class when you're extending another class.
Imagine you're building a custom gaming PC. First, you need to build a basic computer (parent class), THEN you add your gaming-specific parts (child class). super() is like saying "build the basic computer first."
When you create a class that extends another class, JavaScript requires you to call super() in the constructor before you use this.
class Animal {
constructor(name) {
this.name = name;
this.isAlive = true;
}
breathe() {
console.log(`${this.name} is breathing`);
}
}
class Dog extends Animal {
constructor(name, breed) {
super(name); // Call Animal's constructor to set up name and isAlive
this.breed = breed; // Now add Dog-specific properties
}
bark() {
console.log(`${this.name} says Woof!`);
}
}
const myDog = new Dog('Buddy', 'Golden Retriever');
// What happens:
// 1. super('Buddy') calls Animal's constructor
// - Sets this.name = 'Buddy'
// - Sets this.isAlive = true
// 2. Then Dog adds this.breed = 'Golden Retriever'
myDog.breathe(); // Buddy is breathing (inherited from Animal)
myDog.bark(); // Buddy says Woof! (specific to Dog)class Vehicle {
constructor(brand, speed) {
this.brand = brand;
this.speed = speed;
}
move() {
console.log(`${this.brand} is moving at ${this.speed} km/h`);
}
}
class Car extends Vehicle {
constructor(brand, speed, doors) {
super(brand, speed); // Set up Vehicle properties first
this.doors = doors; // Then add Car-specific property
}
honk() {
console.log('Beep beep!');
}
}
class Motorcycle extends Vehicle {
constructor(brand, speed, hasHelmet) {
super(brand, speed); // Set up Vehicle properties first
this.hasHelmet = hasHelmet; // Then add Motorcycle-specific property
}
wheelie() {
console.log('Doing a wheelie!');
}
}
const myCar = new Car('Toyota', 100, 4);
const myBike = new Motorcycle('Yamaha', 150, true);
myCar.move(); // Toyota is moving at 100 km/h (from Vehicle)
myCar.honk(); // Beep beep! (from Car)
myBike.move(); // Yamaha is moving at 150 km/h (from Vehicle)
myBike.wheelie(); // Doing a wheelie! (from Motorcycle)class House {
constructor(address) {
this.address = address;
this.foundation = true;
this.walls = true;
this.roof = true;
}
getInfo() {
console.log(`House at ${this.address}`);
}
}
class SmartHome extends House {
constructor(address, smartDevices) {
super(address); // Build the basic house first
this.smartDevices = smartDevices; // Then add smart features
this.wifi = true;
}
controlLights() {
console.log('Turning on smart lights');
}
}
const myHome = new SmartHome('123 Main St', ['Alexa', 'Smart Thermostat']);
// myHome has:
// - address, foundation, walls, roof (from House via super)
// - smartDevices, wifi (from SmartHome)
myHome.getInfo(); // House at 123 Main St (inherited method)
myHome.controlLights(); // Turning on smart lights (own method)class Parent {
constructor(a, b) {
this.a = a;
this.b = b;
console.log('Parent constructor ran');
}
}
class Child extends Parent {
constructor(a, b, c) {
console.log('Child constructor started');
super(a, b); // Calls Parent's constructor
console.log('Back in Child constructor');
this.c = c;
}
}
const obj = new Child(1, 2, 3);
// Output:
// Child constructor started
// Parent constructor ran
// Back in Child constructor- Must call before using
this:
class Child extends Parent {
constructor() {
this.something = 'value'; // ❌ ERROR! Can't use 'this' before super()
super();
this.something = 'value'; // ✓ Correct! After super()
}
}- Only needed in constructors when extending:
class NotExtending {
constructor() {
// No super() needed - not extending anything
this.value = 10;
}
}
class Extending extends Parent {
constructor() {
super(); // Required when extending
this.value = 10;
}
}- Can also call parent methods:
class Parent {
greet() {
console.log('Hello from Parent');
}
}
class Child extends Parent {
greet() {
super.greet(); // Call parent's greet method
console.log('Hello from Child');
}
}
const obj = new Child();
obj.greet();
// Output:
// Hello from Parent
// Hello from ChildInheritance allows one class to get all the properties and methods from another class. The child class extends the parent class.
It's like you inheriting your parents' traits. You get their eye color, height genes, etc., but you're still your own person with your own unique characteristics.
class Shape {
constructor(color) {
this.color = color;
}
describe() {
console.log(`This is a ${this.color} shape`);
}
}
class Circle extends Shape {
constructor(color, radius) {
super(color); // Get the color from Shape
this.radius = radius;
}
getArea() {
return Math.PI * this.radius * this.radius;
}
}
class Rectangle extends Shape {
constructor(color, width, height) {
super(color); // Get the color from Shape
this.width = width;
this.height = height;
}
getArea() {
return this.width * this.height;
}
}
const redCircle = new Circle('red', 5);
const blueRect = new Rectangle('blue', 4, 6);
redCircle.describe(); // This is a red shape (inherited)
console.log(redCircle.getArea()); // 78.54 (own method)
blueRect.describe(); // This is a blue shape (inherited)
console.log(blueRect.getArea()); // 24 (own method)class GrandParent {
constructor() {
this.generation = 1;
}
}
class Parent extends GrandParent {
constructor() {
super();
this.generation = 2;
}
}
class Child extends Parent {
constructor() {
super();
this.generation = 3;
}
}
const person = new Child();
// Inheritance flows: GrandParent → Parent → ChildKey Points:
- Child class gets all properties and methods from parent
- Child can add new properties and methods
- Child can override parent's methods
- Use
super()to access parent's constructor - Use
super.methodName()to access parent's methods
| Concept | What It Does | Example |
|---|---|---|
| Class | Blueprint for creating objects | class Person { } |
| Constructor | Initializes object when created | constructor(name) { this.name = name; } |
| this | Refers to current object | this.property or this.method() |
| super() | Calls parent class constructor | super(parentArgs) |
| extends | Creates inheritance relationship | class Child extends Parent |
class MyClass {
constructor(value) {
this.value = value;
}
}
const obj = new MyClass(10); // Creates instanceclass Parent {
constructor(a) {
this.a = a;
}
}
class Child extends Parent {
constructor(a, b) {
super(a); // Set up parent
this.b = b; // Add own properties
}
}class MyClass {
myMethod() {
this.anotherMethod(); // Call own method
}
anotherMethod() {
console.log(this.property); // Access own property
}
}- Classes are blueprints for objects
- Constructors initialize objects when they're created
thisrefers to the current object instancesuper()calls the parent class constructor (required when extending)extendscreates an inheritance relationship between classes
These concepts work together to enable object-oriented programming in JavaScript, which is the foundation for implementing design patterns!