JS

Classes & OOP

JavaScript · 8 entries

Class Declaration

syntax
class ClassName {
  constructor(params) { ... }
  method() { ... }
}
example
class Product {
  constructor(name, price) {
    this.name = name;
    this.price = price;
  }

  format() {
    return `${this.name}: $${this.price.toFixed(2)}`;
  }
}

const item = new Product("Notebook", 12.5);
console.log(item.format());
output
"Notebook: $12.50"

Note Classes are syntactic sugar over prototypes. They are NOT hoisted -- you must declare before use, unlike function declarations.

Getters and Setters

syntax
get propertyName() { ... }
set propertyName(value) { ... }
example
class Temperature {
  #celsius;

  constructor(celsius) {
    this.#celsius = celsius;
  }

  get fahrenheit() {
    return this.#celsius * 9 / 5 + 32;
  }

  set fahrenheit(f) {
    this.#celsius = (f - 32) * 5 / 9;
  }

  get celsius() { return this.#celsius; }
}

const temp = new Temperature(100);
console.log(temp.fahrenheit); // 212
temp.fahrenheit = 32;
console.log(temp.celsius);    // 0

Note Getters and setters look like regular properties from the outside. They are ideal for computed values, validation, and encapsulation.

Static Methods and Properties

syntax
class C {
  static method() { ... }
  static property = value;
}
example
class MathUtils {
  static PI = 3.14159265;

  static clamp(value, min, max) {
    return Math.min(Math.max(value, min), max);
  }

  static lerp(a, b, t) {
    return a + (b - a) * t;
  }
}

console.log(MathUtils.clamp(150, 0, 100)); // 100
console.log(MathUtils.lerp(0, 50, 0.5));  // 25

Note Static members belong to the class itself, not instances. Access them via ClassName.method(), not instance.method().

Inheritance (extends)

syntax
class Child extends Parent {
  constructor(params) {
    super(parentParams);
  }
}
example
class Shape {
  constructor(color) {
    this.color = color;
  }
  describe() {
    return `A ${this.color} shape`;
  }
}

class Circle extends Shape {
  constructor(color, radius) {
    super(color);
    this.radius = radius;
  }
  get area() {
    return Math.PI * this.radius ** 2;
  }
  describe() {
    return `A ${this.color} circle (r=${this.radius})`;
  }
}

const c = new Circle("blue", 5);
console.log(c.describe());
console.log(c.area.toFixed(2));
output
"A blue circle (r=5)"
"78.54"

Note super() must be called in the child constructor before accessing this. Methods can be overridden. Use super.method() to call the parent version.

Private Fields and Methods

syntax
class C {
  #privateField = value;
  #privateMethod() { ... }
}
example
class BankAccount {
  #balance = 0;

  constructor(initial) {
    this.#balance = initial;
  }

  deposit(amount) {
    this.#validateAmount(amount);
    this.#balance += amount;
  }

  get balance() {
    return this.#balance;
  }

  #validateAmount(amount) {
    if (amount <= 0) throw new Error("Amount must be positive");
  }
}

const acct = new BankAccount(100);
acct.deposit(50);
console.log(acct.balance);   // 150
// acct.#balance;  // SyntaxError

Note Private fields/methods use the # prefix. They are truly private -- not accessible outside the class, even by subclasses. instanceof checks still work.

Static Initialization Block

syntax
class C {
  static { /* initialization code */ }
}
example
class Config {
  static defaults;
  static env;

  static {
    Config.env = typeof window !== "undefined" ? "browser" : "node";
    Config.defaults = Config.env === "browser"
      ? { timeout: 10000, retries: 2 }
      : { timeout: 30000, retries: 5 };
  }
}

console.log(Config.env);
console.log(Config.defaults);

Note Static blocks run once when the class is evaluated. Useful for complex static initialization that cannot be done in a single expression.

instanceof and Type Checking

syntax
object instanceof ClassName
example
class Animal {}
class Dog extends Animal {}
class Cat extends Animal {}

const pet = new Dog();
console.log(pet instanceof Dog);    // true
console.log(pet instanceof Animal); // true
console.log(pet instanceof Cat);    // false

Note Checks the prototype chain. Can be unreliable across iframes or realms. For built-in types, prefer Array.isArray() over instanceof Array.

Mixins Pattern

syntax
const Mixin = (Base) => class extends Base { ... };
example
const Serializable = (Base) => class extends Base {
  toJSON() {
    return JSON.stringify({ ...this });
  }
};

const Timestamped = (Base) => class extends Base {
  constructor(...args) {
    super(...args);
    this.createdAt = new Date();
  }
};

class User extends Timestamped(Serializable(Object)) {
  constructor(name) {
    super();
    this.name = name;
  }
}

const user = new User("Kai");
console.log(user.toJSON());

Note JavaScript has single inheritance only. Mixins simulate multiple inheritance by composing class factories. Order matters -- later mixins override earlier ones.