Skip to content

Latest commit

 

History

History
534 lines (416 loc) · 12.7 KB

JavaScript-OOP-Reference.md

File metadata and controls

534 lines (416 loc) · 12.7 KB

JavaScript Object-Oriented Programming Reference

This document explains the fundamental OOP concepts used throughout the design patterns examples.


Table of Contents

  1. What is a Class?
  2. What is a Constructor?
  3. What is this?
  4. What is super()?
  5. Inheritance with extends

What is a Class?

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.

Simple Analogy

If you're building houses, a class is the architectural plan. The actual houses built from that plan are the objects (instances).

Basic Example

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 old

Key Points:

  • Classes define properties (what the object has) - like name and age
  • Classes define methods (what the object can do) - like introduce()
  • You create actual objects using the new keyword

What is a Constructor?

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.

Simple Analogy

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."

Example

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 running

Key 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

What is this?

this is a special keyword that refers to the current object. It's like saying "this specific instance" or "myself."

Simple Analogy

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.

Example

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: $600

Key Points:

  • this refers to the object that's currently executing the code
  • this.property accesses a property of the current object
  • this.method() calls a method on the current object
  • Different objects have different this contexts

Common Use Cases

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)

What is super()?

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.

Simple Analogy

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."

Why Do We Need It?

When you create a class that extends another class, JavaScript requires you to call super() in the constructor before you use this.

Example 1: Animal Hierarchy

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)

Example 2: Vehicle Hierarchy

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)

Example 3: Building a House

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)

What Happens When You Call super()?

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

Important Rules for super()

  1. 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()
  }
}
  1. 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;
  }
}
  1. 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 Child

Inheritance with extends

Inheritance allows one class to get all the properties and methods from another class. The child class extends the parent class.

Simple Analogy

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.

Example: Shape Hierarchy

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)

Inheritance Chain

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 → Child

Key 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

Quick Reference

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

Common Patterns

Creating Objects

class MyClass {
  constructor(value) {
    this.value = value;
  }
}

const obj = new MyClass(10);  // Creates instance

Inheritance Pattern

class Parent {
  constructor(a) {
    this.a = a;
  }
}

class Child extends Parent {
  constructor(a, b) {
    super(a);      // Set up parent
    this.b = b;    // Add own properties
  }
}

Method Access

class MyClass {
  myMethod() {
    this.anotherMethod();  // Call own method
  }

  anotherMethod() {
    console.log(this.property);  // Access own property
  }
}

Summary

  • Classes are blueprints for objects
  • Constructors initialize objects when they're created
  • this refers to the current object instance
  • super() calls the parent class constructor (required when extending)
  • extends creates an inheritance relationship between classes

These concepts work together to enable object-oriented programming in JavaScript, which is the foundation for implementing design patterns!