~/hackweb.dev
JavaScript Static Methods & Properties
Quiz
...

JavaScript Static Methods & Properties

beginner · updated Tue Sep 08 2026Contribute

Master static methods, factory methods, and class-level functionality.

JavaScript Static Methods & Properties

Methods and properties that belong to the class itself, not to instances.

Basic Static Methods

class MathUtils {
  static add(a, b) { return a + b; }
  static subtract(a, b) { return a - b; }
  static multiply(a, b) { return a * b; }
}

console.log(MathUtils.add(5, 3));       // 8
console.log(MathUtils.multiply(4, 6));  // 24

Remember: Static methods are called on the class: MathUtils.add(), not new MathUtils().add().

Static Properties

Shared across all instances:

class Counter {
  static count = 0;
  constructor() { Counter.count++; }
  static getCount() { return Counter.count; }
}

new Counter(); new Counter(); new Counter();
console.log(Counter.getCount());  // 3

Factory Methods

Named alternatives to constructors — more readable:

class User {
  constructor(name, email, role) { this.name = name; this.email = email; this.role = role; }

  static createAdmin(name, email) { return new User(name, email, "admin"); }
  static createGuest() { return new User("Guest", "[email protected]", "guest"); }
  static fromJSON(json) {
    let d = JSON.parse(json);
    return new User(d.name, d.email, d.role);
  }
}

let admin = User.createAdmin("John", "[email protected]");

User.createAdmin() is clearer than new User("John", "[email protected]", "admin").

Complete Example: Singleton

class Database {
  static #instance = null;

  constructor() {
    if (Database.#instance) return Database.#instance;
    this.connected = false;
    Database.#instance = this;
  }

  static getInstance() {
    if (!Database.#instance) Database.#instance = new Database();
    return Database.#instance;
  }

  connect() { this.connected = true; return this; }
}

let db1 = Database.getInstance();
let db2 = Database.getInstance();
console.log(db1 === db2);  // true

Complete Example: Builder Pattern

class QueryBuilder {
  #table = ""; #conditions = []; #orderBy = null; #limit = null;

  static from(table) { let b = new QueryBuilder(); b.#table = table; return b; }
  where(c) { this.#conditions.push(c); return this; }
  order(col, dir = "ASC") { this.#orderBy = `${col} ${dir}`; 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.#orderBy) q += ` ORDER BY ${this.#orderBy}`;
    if (this.#limit) q += ` LIMIT ${this.#limit}`;
    return q;
  }
}

let query = QueryBuilder.from("users").where("age > 18").order("name").limit(10).build();

Best Practices

  • Use for utility functions — Don’t need instance state
  • Use for factory methods — Alternative constructors
  • Use static properties — Class-level constants
  • Don’t overuse static — Instance methods are more flexible

Common Mistakes

  • Calling static on an instance — Use ClassName.method()
  • this in static methods — Refers to the class, not an instance
  • Forgetting static keyword — Method becomes an instance method
  • Overusing static — Prefer instance methods for most logic