JavaScript **classes** are syntactic sugar over prototype-based inheritance. They support a `constructor` method (called with new), instance methods, **static methods** (called on the class itself), **getters/setters**, and **private fields** (`#field`). Classes are **not hoisted** like function declarations.
1Understanding Classes
JavaScript classes are syntactic sugar over prototype-based inheritance. They support a constructor method (called with new), instance methods, static methods (called on the class itself), getters/setters, and private fields (#field). Classes are not hoisted like function declarations.
Classes are NOT just syntactic sugar — they enforce strict mode, cannot be called without new, and support private fields (#) which proto-based code cannot do cleanly.
class BankAccount {
#balance = 0; // private field
constructor(owner) { this.owner = owner; }
deposit(amount) { this.#balance += amount; }
withdraw(amount) {
if (amount > this.#balance) throw new Error('Insufficient funds');
this.#balance -= amount;
}
get balance() { return this.#balance; }
}
const acc = new BankAccount('Alice');
acc.deposit(100);
acc.withdraw(30);
console.log(acc.balance); // 702Practical Example
Here is a real-world application of Classes showing how it is used in production JavaScript code.
// Static factory method
class Color {
constructor(r, g, b) { this.r = r; this.g = g; this.b = b; }
toString() { return `rgb(${this.r},${this.g},${this.b})`; }
static fromHex(hex) {
const r = parseInt(hex.slice(1,3), 16);
const g = parseInt(hex.slice(3,5), 16);
const b = parseInt(hex.slice(5,7), 16);
return new Color(r, g, b);
}
}
console.log(Color.fromHex('#FF8800').toString());3Best Practices
Follow these guidelines when working with Classes:
1. Use classes for complex objects with shared behavior
2. Use private fields (#) for encapsulation
3. Use static methods for factory functions and utilities
Tip: Classes are NOT just syntactic sugar — they enforce strict mode, cannot be called without new, and support private fields (#) which proto-based code cannot do cleanly.
class BankAccount {
#balance = 0; // private field
constructor(owner) { this.owner = owner; }
deposit(amount) { this.#balance += amount; }
withdraw(amount) {
if (amount > this.#balance) throw new Error('Insufficient funds');
this.#balance -= amount;
}
get balance() { return this.#balance; }
}
const acc = new BankAccount('Alice');
acc.deposit(100);
acc.withdraw(30);
console.log(acc.balance); // 70