Appearance
Classes
The class syntax in JavaScript is "syntactic sugar" over the prototype-based object system. It provides familiar object-oriented terminology and structure for defining constructors, methods, and access controls, but operates on the same prototype mechanics underneath.
Class Syntax
Let's convert our Shape constructor function to a class:
js
// Instead of this constructor function and prototype:
function Shape(colour) {
this.colour = colour;
}
Shape.prototype.draw = function() {
return `A ${this.colour} shape.`;
};
// We can write this class:
class Shape {
constructor(colour) {
this.colour = colour;
}
draw() {
return `A ${this.colour} shape.`;
}
}
// They're used the same way
const shape = new Shape("red");
console.log(shape.draw()); // "A red shape"Properties
Like all objects in JavaScript, class instances are accessed through references. When using const, you can still modify the instance's properties through this reference, you just can't make the variable reference a different instance.
Properties can be defined in the constructor or in the class body:
js
class Rectangle {
// Properties defined in class body
width = 0;
height = 0;
colour = "white"; // Default value
// Properties that need constructor values
constructor(w, h) {
this.width = w;
this.height = h;
}
}Methods
Methods in classes are defined similarly to object literals, without the function keyword:
js
class Shape {
colour = "white"; // Default colour
// Method that returns a value
draw() {
return `A ${this.colour} shape`;
}
// Method with parameters
scale(factor) {
return `Shape scaled by ${factor}`;
}
}
const shape = new Shape();
console.log(shape.draw()); // "A white shape"
console.log(shape.scale(2)); // "Shape scaled by 2"The this Keyword
Inside class methods, this refers to the instance of the class:
js
class Counter {
count = 0;
increment() {
this.count += 1; // 'this' refers to the Counter instance
}
getTotal() {
return this.count; // Access instance property
}
}
const counter = new Counter();
counter.increment();
console.log(counter.getTotal()); // 1Private Fields
You can make properties private using #:
js
class BankAccount {
#balance = 0; // Private property
deposit(amount) {
this.#balance += amount;
}
getBalance() {
return this.#balance;
}
}
const account = new BankAccount();
account.deposit(100);
console.log(account.getBalance()); // 100
// console.log(account.#balance); // Error: private fieldGetters and Setters
The get and set keywords let you control how properties are accessed and modified. This is useful when you need to:
- Validate values before setting them
- Compute values on demand
- Make properties read-only
- Log access to properties
Here's an example using a private field with the # prefix:
js
class Circle {
#radius = 0; // Private field
// Getter and setter for radius
get radius() {
return this.#radius;
}
set radius(value) {
if (value < 0) {
throw new Error("Radius cannot be negative");
}
this.#radius = value;
}
// Computed property
get area() {
return Math.PI * this.#radius * this.#radius;
}
}
const circle = new Circle();
circle.radius = 5; // Uses setter
console.log(circle.area); // Uses getter: ~78.54
circle.radius = -1; // Error: Radius cannot be negative
// console.log(circle.#radius); // SyntaxError: Private field '#radius' must be declared in an enclosing classYou can also use getters to make properties read-only:
js
class BankAccount {
#balance = 100; // Private field
// Only getter, no setter = read-only property
get balance() {
return this.#balance;
}
}
const account = new BankAccount();
console.log(account.balance); // 100
account.balance = 50; // No effect (or error in strict mode)
// console.log(account.#balance); // SyntaxError: Private field '#balance'
// must be declared in an enclosing class💡 While classes are just syntax over prototypes, they're the preferred way to create objects with shared behaviour in modern JavaScript.
External Resources