ES6+ Features: Classes Introduction
Before ES2015 (ES6), JavaScript used constructor functions and prototypes to achieve object-oriented patterns. While powerful, this approach could be confusing for developers coming from class-based languages like Java or C++. ES6 Classes were introduced as syntactic sugar over JavaScript's existing prototype-based inheritance model, providing a cleaner, more familiar syntax for creating "blueprints" for objects.
They don't introduce a new object-oriented inheritance model, but rather a more intuitive way to work with the existing one.
1. Defining a Class
A class is defined using the class keyword, followed by the class name (conventionally PascalCase, e.g., MyClass).
The constructor Method
Every class can have a special method called constructor.
- It's automatically called when a new object (an "instance") of the class is created using the
newkeyword. - It's used to initialize the properties of the new object.
- Inside the
constructor(and other class methods), thethiskeyword refers to the instance of the class being created.
Syntax:
class ClassName {
constructor(param1, param2) {
this.property1 = param1;
this.property2 = param2;
}
}
2. Class Methods
Methods are functions defined inside the class that operate on the instance's data. They are defined directly within the class body, without the function keyword.
These methods are automatically added to the class's prototype, meaning all instances of the class share the same method definitions, saving memory.
Syntax:
class ClassName {
constructor(name) {
this.name = name;
}
// A method
greet() {
return 'Hello, my name is ' + this.name + '!';
}
// Another method
sayGoodbye() {
return 'Goodbye!';
}
}
3. Creating Instances
To create a new object (an "instance") from a class, you use the new keyword followed by the class name and any arguments for its constructor.
const instanceName = new ClassName(arg1, arg2);
4. Getters and Setters
Getters and setters are special methods that allow you to define computed properties for a class. They provide a way to execute code when a property is accessed (get) or set (set), allowing for validation or derived values.
get propertyName(): A method that returns a value when a property is accessed.set propertyName(value): A method that sets a value when a property is assigned.
class Circle {
constructor(radius) {
this._radius = radius; // Use a convention like _propertyName for the actual storage
}
get radius() {
console.log('Getting radius...');
return this._radius;
}
set radius(newRadius) {
console.log('Setting radius to: ' + newRadius);
if (newRadius > 0) {
this._radius = newRadius;
} else {
console.warn('Radius must be positive!');
}
}
get diameter() {
return this._radius * 2;
}
}
5. Static Methods
Static methods are methods that belong to the class itself, not to instances of the class. They are called directly on the class name (e.g., ClassName.staticMethod()) and cannot access instance-specific data (this). They are useful for utility functions that relate to the class but don't require an instance.
class MathUtility {
static add(a, b) {
return a + b;
}
static PI = 3.14159; // Static field (ES2022)
}
// Usage:
// MathUtility.add(5, 3); // 8
// MathUtility.PI; // 3.14159
6. Class Fields (Public and Private - Brief Mention)
A newer addition to ES classes are class fields, which allow defining properties directly in the class body.
- Public Class Fields:
propertyName = value;Properties defined this way are added directly to the instance when it's created. - Private Class Fields:
#propertyName = value;Properties prefixed with#are truly private to the class and cannot be accessed from outside the class or by instances.
class PersonWithFields {
name = 'Anonymous'; // Public field
#privateId = 'xyz123'; // Private field (only accessible inside the class)
constructor(name) {
if (name) this.name = name;
}
getPrivateId() {
return this.#privateId;
}
}
7. No Hoisting for Classes
Unlike function declarations (which are hoisted), class declarations are not hoisted. This means you must define a class before you can create an instance of it. Trying to use a class before its declaration will result in a ReferenceError.
// new MyClass(); // ReferenceError: Cannot access 'MyClass' before initialization
class MyClass {} // Class definition
Comprehensive Example: The Book Class
Let's put these concepts together with a Book class.
Exercise: Create a Vehicle Class
Instructions:
Create a new ES6 class named Vehicle with the following requirements:
- Constructor:
- Takes
make,model, andyearas arguments. - Initialize these as instance properties.
- Log a message when a new vehicle is created (e.g., "New [make] [model] created!").
- Takes
getDetails()Method:- An instance method that returns a string like: "
[year] [make] [model]".
- An instance method that returns a string like: "
start()Method:- An instance method that logs: "
[make] [model] is starting the engine!".
- An instance method that logs: "
ageGetter:- A getter property that calculates and returns the age of the vehicle based on its
yearand the current year.
- A getter property that calculates and returns the age of the vehicle based on its
isVintageStatic Getter:- A static getter property that checks if the
Vehicleclass itself is considered vintage (e.g.,trueifVehicle.MIN_VINTAGE_YEARis less than 1950, otherwisefalse).
- A static getter property that checks if the
MIN_VINTAGE_YEARStatic Field:- A static class field initialized to
1990.
- A static class field initialized to
- Test your class by creating two instances and calling their methods and accessing their properties. Also, access the static properties.

