JavaScript static properties are properties that belong to a class itself rather than to individual objects created from that class. You can use them to store shared information, configuration values, counters, and other data related to the class as a whole. Static properties are accessed through the class name, and they can also be inherited by child classes.
What Are Static Properties in JavaScript?
A static property is a property defined on a class constructor instead of on its instances. Unlike an instance property, which usually belongs to each object created with new, a static property is shared at the class level.
JavaScript supports static class fields using the static keyword. Public static class fields became part of the ECMAScript standard in ES2022. Static properties are useful when a value describes the class itself rather than one particular object.
Basic Syntax of JavaScript Static Properties
To declare a static property, write the static keyword before the property name inside the class body.
class User {
static role = "General User";
}
console.log(User.role); // "General User"
In this example, role belongs to the User class. You access it as User.role without creating an instance with new User().
Accessing Static Properties Using the Class Name
Static properties are accessed directly through the class name. Creating an object from the class does not make a static property available as an ordinary instance property.
class Company {
static companyName = "Learnings Edu";
}
console.log(Company.companyName); // "Learnings Edu"
const company1 = new Company();
// This does not read the static property:
// console.log(company1.companyName); // undefined
The companyName property belongs to the Company constructor. The company1 object does not have that property, so reading company1.companyName returns undefined unless an instance property or another inherited property with that name exists.
Static Properties vs. Instance Properties
Instance properties store data for an individual object. Static properties store data associated with the class itself. Each instance can have its own value for an instance property, while a static property is stored on the class constructor.
class Student {
static schoolName = "City College";
constructor(name) {
this.name = name;
}
}
const student1 = new Student("Ava");
const student2 = new Student("Rahim");
console.log(student1.name); // "Ava"
console.log(student2.name); // "Rahim"
console.log(Student.schoolName); // "City College"
Each student has a separate name property, but the school name is associated with the Student class. Both students belong to the same class, so the shared school information is stored as a static property.
Updating Static Properties
You can update a public static property by assigning a new value through the class name. The updated value is then available to code that reads that class property.
class Counter {
static count = 0;
}
Counter.count = 10;
console.log(Counter.count); // 10
Counter.count++;
console.log(Counter.count); // 11
Because count is static, the value is stored on the Counter class. It is not automatically copied into each object created from that class.
Using Static Properties with Static Methods
Static methods can read and update static properties. Inside a static method, this normally refers to the class on which the method was called. This is useful for keeping class-level data and class-level operations together.
class Employee {
static employeeCount = 0;
constructor(name) {
this.name = name;
Employee.employeeCount++;
}
static getCount() {
return this.employeeCount;
}
}
const employee1 = new Employee("Nadia");
const employee2 = new Employee("Rafi");
console.log(Employee.getCount()); // 2
Each time an Employee object is created, the constructor increases the class’s employeeCount. The static getCount() method returns the shared count. Notice that the constructor uses Employee.employeeCount, because this inside an instance constructor refers to the new employee object.
Static Properties and JavaScript Inheritance
When one class extends another class, the child class can access inherited static properties through the constructor’s prototype chain. The child class can read a static property defined by its parent unless it defines a property with the same name of its own.
class Animal {
static category = "Living Creature";
}
class Dog extends Animal {}
console.log(Animal.category); // "Living Creature"
console.log(Dog.category); // "Living Creature"
The Dog class inherits access to category from Animal. Static inheritance works through the relationship between the class constructors; it does not mean that every dog instance receives a category property.
Overriding Static Properties in a Child Class
A child class can declare a static property with the same name as a property in its parent class. The child class’s own property takes precedence when accessed through the child class. This is commonly called shadowing.
class Animal {
static category = "Animal";
}
class Dog extends Animal {
static category = "Domestic Animal";
}
console.log(Animal.category); // "Animal"
console.log(Dog.category); // "Domestic Animal"
The original value on Animal remains unchanged. The Dog class defines its own static property, which is used when you access Dog.category.
Using this in Static Properties and Methods
A static method can use this to refer to the class that receives the method call. This allows an inherited static method to work with a static property on the child class when that property is defined there.
class User {
static type = "User";
static getType() {
return this.type;
}
}
class Admin extends User {
static type = "Administrator";
}
console.log(User.getType()); // "User"
console.log(Admin.getType()); // "Administrator"
The inherited getType() method is called first on User and then on Admin. In each call, this refers to the class used as the receiver, so the method reads the appropriate static type property.
Private Static Properties in JavaScript
JavaScript also supports private static fields. A private static property is declared with a hash (#) before its name and can only be accessed from within the class body that declares it. This helps keep class-level implementation details hidden from outside code.
class Account {
static #accountCount = 0;
constructor(owner) {
this.owner = owner;
Account.#accountCount++;
}
static getAccountCount() {
return Account.#accountCount;
}
}
const account1 = new Account("Ava");
const account2 = new Account("Rahim");
console.log(Account.getAccountCount()); // 2
// Not allowed outside the class:
// console.log(Account.#accountCount);
The #accountCount field is private and cannot be accessed directly from outside the Account class. The public static method getAccountCount() provides a controlled way to read its value.
Static Getters and Setters
You can define static getters and setters in a class. They are accessor properties on the class itself, not on individual instances. A static getter can calculate or return a class-level value, while a static setter can validate and update a static property.
class Product {
static _taxRate = 0.15;
static get taxRate() {
return this._taxRate;
}
static set taxRate(value) {
if (typeof value !== "number" || value < 0) {
throw new TypeError("Tax rate must be a non-negative number.");
}
this._taxRate = value;
}
}
console.log(Product.taxRate); // 0.15
Product.taxRate = 0.2;
console.log(Product.taxRate); // 0.2
The taxRate getter and setter are accessed through Product. The setter checks the new value before storing it in the backing property _taxRate.
Static Initialization Blocks
JavaScript classes also support static initialization blocks. A static block is declared with static followed by braces and runs once when the class is initialized. It can initialize or validate static fields and can access the class’s private static fields.
class Configuration {
static environment = "development";
static debug;
static {
this.debug = this.environment !== "production";
}
}
console.log(Configuration.debug); // true
Static initialization blocks are different from static properties: the property stores a value, while the block runs statements to perform initialization. They are useful when static initialization requires more than a simple assignment.
Static Properties in Built-in JavaScript Classes
JavaScript’s built-in constructors also provide static properties. For example, Number has constants describing numeric limits, and Math provides mathematical constants.
console.log(Number.MAX_VALUE);
console.log(Number.MIN_VALUE);
console.log(Math.PI);
console.log(Math.E);
These values are accessed through their respective built-in objects, such as Number.MAX_VALUE and Math.PI. They are not accessed through individual number instances.
When Should You Use Static Properties?
Static properties are useful when data belongs to a class as a whole and should not be duplicated across every instance. Common examples include shared counters, default configuration, application-wide constants related to a class, and private class-level state.
Use an instance property when each object needs its own value, such as a student’s name or an employee’s salary. Choose a static property when the value describes the class or is intentionally shared at the class level.
