The Class Abstraction
ECMAScript 2015 introduced the class syntax to provide a more familiar organizational structure for developers coming from languages like Java or C++. However, as previously established, this is an abstraction over the prototype chain. Classes in JavaScript are essentially special functions.
Structure of a Class
A class definition typically includes a constructor, methods, and optionally, static members.
class Spacecraft {
constructor(name, range) {
this.name = name;
this.range = range;
}
// Prototype method
launch() {
return `${this.name} is entering orbit.`;
}
// Static method (on the class itself, not instances)
static getManufacturer() {
return "Void Dynamics Corp.";
}
}
Static Members and the this Context
Static methods and properties are defined on the class itself rather than on the instance. Inside a static method, this refers to the class constructor, not an object instance. Static members are often used for utility functions or factory methods.
Private Fields and Encapsulation
Historically, JavaScript developers used a convention of prefixing properties with an underscore (e.g., _secret) to signal that they should be treated as private. However, this was purely a convention and did not prevent external access.
Modern JavaScript (ES2022+) supports Private Class Fields using the # prefix. These fields are truly encapsulated; they cannot be accessed or modified from outside the class body, even through property indexing.
Inheritance with extends and super
The extends keyword allows a class to inherit from another class. The super() call inside the constructor is mandatory before accessing this, as it initializes the parent class and binds the instance.
class Rocket extends Spacecraft {
constructor(name, range, fuelType) {
super(name, range); // Call parent constructor
this.fuelType = fuelType;
}
// Method overriding
launch() {
return `${super.launch()} Igniting ${this.fuelType} boosters.`;
}
}
Getters and Setters
Classes support get and set keywords to define computed properties or interpose logic during property access/assignment. This allows for validation and transformation while maintaining a property-like interface.
What happens if you attempt to access a private field (e.g., #data) from outside the class where it is defined?
Performance of Classes
While classes provide a clean syntax, they carry the same performance characteristics as prototypal inheritance. The method lookup still involves traversing the prototype chain. However, modern engines optimize class-based structures very effectively because the fixed shape of class instances allows for stable inline caches and optimized machine code generation.