Classes
Objectives
By the end of this lesson, you should be able to:
- Define a class with a constructor and methods
- Extend a class and override a method with
super - Use a private field and a static method
💡 Why this matters: Classes show up constantly in real Node.js and Express code, custom error types (Module 8), and structured models representing real-world data (starting in the next course, with a database behind them).
⚠️ A note on verification: every snippet and output in this lesson was actually run with Node.js.
Defining a Class
class Employee {
#salary;
constructor(name, department, salary) {
this.name = name;
this.department = department;
this.#salary = salary;
}
describe() {
return `${this.name} works in ${this.department}`;
}
get salary() {
return this.#salary;
}
static fromObject(obj) {
return new Employee(obj.name, obj.department, obj.salary);
}
}
const erin = new Employee("Erin", "Engineering", 74000);
console.log(erin.describe());
console.log(erin.salary);
Erin works in Engineering
74000
The constructor runs when new Employee(...) is called, setting up the instance’s initial state. describe() is a regular method, callable on any instance. #salary is a private field, # marks it as inaccessible from outside the class entirely, not even readable directly as erin.#salary, the get salary() method exposes a controlled, read-only way to access it instead.
Static Methods
const fromData = Employee.fromObject({ name: "Jordan", department: "Sales", salary: 61000 });
console.log(fromData.describe());
Jordan works in Sales
static fromObject(obj) belongs to the class itself, not to any individual instance, called as Employee.fromObject(...), never erin.fromObject(...). Static methods are common for alternative ways to construct an instance, here, building one from a plain object instead of separate arguments.
Inheritance with extends and super
class Manager extends Employee {
constructor(name, department, salary, teamSize) {
super(name, department, salary);
this.teamSize = teamSize;
}
describe() {
return `${super.describe()}, managing a team of ${this.teamSize}`;
}
}
const priya = new Manager("Priya", "Engineering", 89000, 4);
console.log(priya.describe());
Priya works in Engineering, managing a team of 4
extends Employee makes Manager a subclass, inheriting everything Employee has. super(...) inside the constructor calls Employee’s own constructor first, required before using this in a subclass’s constructor. super.describe() inside the overridden describe() method calls the parent’s version specifically, then builds on top of it, rather than replacing it entirely.
Try It
- Define a class
Productwith a constructor takingnameandprice, and a methoddescribe()returning a formatted string. - Add a private field
#discountCodeand a getter that exposes it read-only. - Create a subclass
DigitalProduct extends Productthat adds adownloadUrlproperty, and overridesdescribe()to include it, callingsuper.describe()inside the override. - Add a static method
Product.fromObject(obj)that constructs aProductfrom a plain object.
Recap
- A class’s
constructorsets up instance state, methods are shared across every instance. #fielddeclares a private field, only accessible from inside the class, a getter can expose it in a controlled way.staticmethods belong to the class itself, not an instance,extendsandsuperimplement inheritance, overriding a method while still being able to call the parent’s version.
Next lesson: error handling, catching and throwing errors correctly.