Why use static class members?
By FrontendPro Editorial Team Updated 9/26/2026
Answer
A static member belongs to the class itself, not to instances. You use it for anything that is about the type as a whole rather than about one object: alternative constructors, shared constants, utilities, and instance counters.
class User {
static ROLES = ['admin', 'member']; // shared constant
static #count = 0; // private to the class
constructor(name) { this.name = name; User.#count++; }
static fromJSON(json) { // named constructor
return new User(JSON.parse(json).name);
}
static get count() { return User.#count; }
}
User.ROLES; // on the class
User.fromJSON('{"name":"Mai"}');
new User('Linh').ROLES; // undefined — NOT on instances
The four real uses
- Factory / named constructors.
Date.now(),Array.from(),Promise.resolve(). A constructor can only have one signature; static methods give you as many entry points as you need, each with a name that says what it does. - Constants and configuration that are identical for every instance. Putting them on the prototype or in the constructor would copy or indirect them for no reason.
- Utilities that conceptually belong to the type but need no instance:
Number.isInteger,Object.keys, aUser.validate(email). - Class-level state: an instance count, a registry, a memo cache shared by all instances.
The details worth knowing
Inside a static method, this is the class, which is why static create() { return new this(); } works correctly in a subclass. Statics are inherited through the class's own prototype chain, so a subclass can call and override them.
A static initialisation block runs once, when the class is defined, for setup that needs statements:
class Config {
static values;
static { Config.values = loadDefaults(); }
}
When not to bother
If there is no instance state and no inheritance, a class full of statics is just a namespace — a module with exported functions is simpler and tree-shakes better. And static state is global state, with all the testability problems that implies: it survives between tests unless you reset it.
