JavaScript Classes
Classes are a way to create objects that share the same structure and behaviour. They make it easier to create multiple objects of the same type without repeating yourself.
Under the hood, JavaScript classes are syntactic sugar over the prototype system. They do not introduce a new object model; they just make the syntax cleaner and more familiar if you have used other languages. See Prototypes for the underlying mechanics.
Defining a class
Use the class keyword followed by a PascalCase name.
class Person {
// code goes here
}
Constructor
The constructor is a special method that runs when you create a new instance with new. Use it to set up the initial state of the object.
class Person {
constructor(firstName, lastName, birthYear) {
this.firstName = firstName;
this.lastName = lastName;
this.birthYear = birthYear;
}
}
Each class can only have one constructor. Writing two will throw a SyntaxError.
Creating instances
Use new to create an object from a class.
const p1 = new Person('Anna', 'Wood', 1995);
const p2 = new Person('Joe', 'Hopkins', 1990);
console.log(p1.firstName); // Anna
console.log(p2.birthYear); // 1990
Methods
Methods are functions defined inside the class body. They are available on every instance.
class Person {
constructor(firstName, lastName, birthYear) {
this.firstName = firstName;
this.lastName = lastName;
this.birthYear = birthYear;
}
getFullName() {
return `${this.firstName} ${this.lastName}`;
}
getAge() {
return new Date().getFullYear() - this.birthYear;
}
}
const p1 = new Person('Anna', 'Wood', 1995);
console.log(p1.getFullName()); // Anna Wood
console.log(p1.getAge()); // 30 (in 2025)
Getters and setters
Getters and setters let you access computed values like properties and add validation when setting values.
class Temperature {
constructor(celsius) {
this._celsius = celsius;
}
get fahrenheit() {
return this._celsius * 1.8 + 32;
}
get celsius() {
return this._celsius;
}
set celsius(value) {
if (value < -273.15) {
throw new Error('Temperature below absolute zero');
}
this._celsius = value;
}
}
const temp = new Temperature(100);
console.log(temp.fahrenheit); // 212
console.log(temp.celsius); // 100
temp.celsius = 0;
console.log(temp.fahrenheit); // 32
You access a getter with dot notation (no parentheses), like a regular property.
Private class fields
Private fields (ES2022) start with # and can only be accessed inside the class. This is true privacy, not just a naming convention.
class BankAccount {
#balance = 0; // private field
deposit(amount) {
if (amount <= 0) throw new Error('Amount must be positive');
this.#balance += amount;
}
withdraw(amount) {
if (amount > this.#balance) throw new Error('Insufficient funds');
this.#balance -= amount;
}
getBalance() {
return this.#balance;
}
}
const account = new BankAccount();
account.deposit(100);
account.withdraw(30);
console.log(account.getBalance()); // 70
// This throws a SyntaxError: you cannot access private fields from outside
console.log(account.#balance);
Static methods
Static methods belong to the class itself, not to any instance. Call them on the class directly.
class MathHelper {
static square(n) {
return n * n;
}
static cube(n) {
return n * n * n;
}
static generateId() {
return Math.floor(Math.random() * 10000);
}
}
console.log(MathHelper.square(4)); // 16
console.log(MathHelper.cube(3)); // 27
console.log(MathHelper.generateId()); // random number
Static methods are useful for utility functions that are logically related to the class but do not need an instance.
Inheritance
A subclass extends a parent class with the extends keyword. It inherits all the parent’s methods. Call super() in the subclass constructor to run the parent constructor first.
class Person {
constructor(firstName, lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
getFullName() {
return `${this.firstName} ${this.lastName}`;
}
}
class Student extends Person {
constructor(firstName, lastName, school) {
super(firstName, lastName); // must call super() first
this.school = school;
}
getInfo() {
return `${this.getFullName()} attends ${this.school}`;
}
}
const s1 = new Student('John', 'Smith', 'MIT');
console.log(s1.getInfo()); // John Smith attends MIT
console.log(s1.getFullName()); // John Smith (inherited from Person)
Common mistakes
Forgetting super() in a subclass constructor
If you write a constructor in a subclass, you must call super() before you access this. If you forget, you get a ReferenceError.
Using this in a static method
Static methods do not have access to instance properties. Inside a static method, this refers to the class itself, not an instance.
class Counter {
count = 0; // instance field
static reset() {
this.count = 0; // wrong: this is the Counter class, not an instance
}
}
Expecting private field access from outside the class
Private fields with # throw a SyntaxError if you try to access them outside the class. This is intentional and the whole point of using them.
What to read next
- Prototypes : the underlying system classes are built on
- Constructor functions : how objects were created before the class syntax