JavaScript Cheatsheet

Classes

Use this JavaScript reference while you build software engineering projects, review code for technical interview prep, or polish examples for a software engineer resume.

Class Declaration

class Animal {
  // Public class field (ES2022)
  species = "unknown";

  constructor(name, sound) {
    this.name = name;
    this.sound = sound;
  }

  // Instance method
  speak() {
    return `${this.name} says ${this.sound}`;
  }

  // Getter
  get info() {
    return `${this.name} (${this.species})`;
  }

  // Setter
  set info(val) {
    [this.name] = val.split(" ");
  }

  // Static method — called on class, not instance
  static create(name) {
    return new Animal(name, "...");
  }

  // toString for coercion
  toString() {
    return this.name;
  }
}

const dog = new Animal("Rex", "woof");
dog.speak()          // "Rex says woof"
Animal.create("Cat") // Animal instance

Class Expression

// Named class expression (name only in scope inside)
const Animal = class AnimalClass {
  constructor(name) { this.name = name; }
};

// Anonymous class expression
const Animal2 = class {
  constructor(name) { this.name = name; }
};

Public and Private Fields (ES2022)

class Counter {
  // Public field with default
  count = 0;

  // Private field — only accessible inside the class body
  #step;
  #history = [];

  constructor(step = 1) {
    this.#step = step;
  }

  increment() {
    this.count += this.#step;
    this.#history.push(this.count);
    return this;
  }

  get history() { return [...this.#history]; }

  // Private method
  #validate(n) {
    return Number.isInteger(n) && n > 0;
  }

  // Static private
  static #instances = 0;
  static getCount() { return Counter.#instances; }
}

const c = new Counter(2);
c.increment().increment();
c.count    // 4
c.#step    // SyntaxError — private
"#step" in c  // false  (private field check)

Static Members

class MathUtils {
  // Static field
  static PI = 3.14159;

  // Static method
  static square(n) { return n * n; }
  static cube(n)   { return n ** 3; }

  // Static getter
  static get version() { return "1.0"; }
}

MathUtils.PI          // 3.14159
MathUtils.square(4)   // 16
MathUtils.version     // "1.0"

// Static block (ES2022) — complex initialization
class Config {
  static DEBUG;
  static {
    Config.DEBUG = process.env.NODE_ENV !== "production";
  }
}

Inheritance

class Dog extends Animal {
  constructor(name, breed) {
    super(name, "woof"); // must call super() before using `this`
    this.breed = breed;
  }

  // Override
  speak() {
    return super.speak() + "!"; // call parent method
  }

  fetch() { return `${this.name} fetches the ball`; }
}

const rex = new Dog("Rex", "Labrador");
rex.speak()          // "Rex says woof!"
rex instanceof Dog   // true
rex instanceof Animal // true

// Check prototype chain
Object.getPrototypeOf(Dog.prototype) === Animal.prototype // true

Inheritance with Private Fields

class Base {
  #value;
  constructor(v) { this.#value = v; }
  getValue() { return this.#value; }
}

class Derived extends Base {
  #extra;
  constructor(v, extra) {
    super(v);
    this.#extra = extra;
  }
  getAll() { return [this.getValue(), this.#extra]; }
}

Getters and Setters

class Temperature {
  #celsius;

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

  get celsius()    { return this.#celsius; }
  set celsius(val) {
    if (val < -273.15) throw new RangeError("Below absolute zero");
    this.#celsius = val;
  }

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

  get kelvin()    { return this.#celsius + 273.15; }
}

const t = new Temperature(100);
t.fahrenheit   // 212
t.celsius = -10;
t.kelvin       // 263.15

Mixins

// Mixin — add reusable behavior via Object.assign to prototype
const Serializable = (Base) => class extends Base {
  serialize() { return JSON.stringify(this); }
  static deserialize(json) { return Object.assign(new this(), JSON.parse(json)); }
};

const Validatable = (Base) => class extends Base {
  validate() { return Object.keys(this).every(k => this[k] !== null); }
};

class Model {}
class User extends Serializable(Validatable(Model)) {
  constructor(name, age) {
    super();
    this.name = name;
    this.age = age;
  }
}

const u = new User("Alice", 30);
u.serialize();  // '{"name":"Alice","age":30}'
u.validate();   // true

Abstract-Like Patterns

// JavaScript has no abstract keyword — enforce in constructor
class Shape {
  constructor() {
    if (new.target === Shape) {
      throw new TypeError("Cannot instantiate abstract class Shape");
    }
  }
  // Abstract method — must be overridden
  area() { throw new Error("area() must be implemented"); }
  toString() { return `${this.constructor.name}(area=${this.area()})`; }
}

class Circle extends Shape {
  #r;
  constructor(r) { super(); this.#r = r; }
  area() { return Math.PI * this.#r ** 2; }
}

new Shape()        // TypeError
new Circle(5).area() // 78.53...

Class vs Function Constructor

// ES5 constructor function
function PersonOld(name) {
  this.name = name;
}
PersonOld.prototype.greet = function() { return `Hi, ${this.name}`; };

// ES6 class (syntactic sugar over prototype chain)
class Person {
  constructor(name) { this.name = name; }
  greet() { return `Hi, ${this.name}`; }
}

// Both produce same prototype structure:
const p = new Person("Alice");
typeof Person               // "function"
Person.prototype.greet      // exists
p.__proto__ === Person.prototype // true

// Key difference: classes must be called with new; functions don't enforce it

Useful Patterns

// Fluent interface (method chaining)
class QueryBuilder {
  #table = "";
  #conditions = [];
  #limit = null;

  from(table)  { this.#table = table; return this; }
  where(cond)  { this.#conditions.push(cond); return this; }
  limit(n)     { this.#limit = n; return this; }

  build() {
    let q = `SELECT * FROM ${this.#table}`;
    if (this.#conditions.length) q += ` WHERE ${this.#conditions.join(" AND ")}`;
    if (this.#limit !== null) q += ` LIMIT ${this.#limit}`;
    return q;
  }
}

new QueryBuilder().from("users").where("age > 18").limit(10).build();
// "SELECT * FROM users WHERE age > 18 LIMIT 10"

// Singleton
class Singleton {
  static #instance = null;
  static getInstance() {
    if (!Singleton.#instance) Singleton.#instance = new Singleton();
    return Singleton.#instance;
  }
}

// Factory method
class Animal2 {
  static create(type, name) {
    switch (type) {
      case "dog": return new Dog(name);
      case "cat": return new Cat(name);
      default: throw new Error(`Unknown type: ${type}`);
    }
  }
}

Symbol.iterator and Custom Iterables

class Range {
  constructor(start, end, step = 1) {
    this.start = start;
    this.end = end;
    this.step = step;
  }

  [Symbol.iterator]() {
    let current = this.start;
    const { end, step } = this;
    return {
      next() {
        if (current < end) {
          const value = current;
          current += step;
          return { value, done: false };
        }
        return { value: undefined, done: true };
      },
    };
  }
}

const r = new Range(1, 10, 2);
[...r]         // [1, 3, 5, 7, 9]
for (const n of r) console.log(n);