Classes in JS
ES6 classes provide a cleaner syntax for creating objects and implementing inheritance in JavaScript.
Basic Class Syntax
javascript// Class declaration class Person { constructor(name, age) { this.name = name; this.age = age; } // Method greet() { return `Hello, I'm ${this.name} and I'm ${this.age} years old`; } // Static method static species() { return 'Homo sapiens'; } } // Creating instances const person1 = new Person('Alice', 30); const person2 = new Person('Bob', 25); console.log(person1.greet()); // Hello, I'm Alice and I'm 30 years old console.log(Person.species()); // Homo sapiens
Class Inheritance
javascript// Parent class class Animal { constructor(name, species) { this.name = name; this.species = species; } makeSound() { return 'Some generic animal sound'; } info() { return `${this.name} is a ${this.species}`; } } // Child class class Dog extends Animal { constructor(name, breed) { super(name, 'Dog'); // Call parent constructor this.breed = breed; } // Override parent method makeSound() { return 'Woof! Woof!'; } // New method wagTail() { return `${this.name} is wagging tail happily!`; } } const dog = new Dog('Buddy', 'Golden Retriever'); console.log(dog.info()); // Buddy is a Dog console.log(dog.makeSound()); // Woof! Woof! console.log(dog.wagTail()); // Buddy is wagging tail happily!
Getters and Setters
javascriptclass Rectangle { constructor(width, height) { this._width = width; this._height = height; } // Getter get area() { return this._width * this._height; } get perimeter() { return 2 * (this._width + this._height); } // Setter set width(value) { if (value > 0) { this._width = value; } else { throw new Error('Width must be positive'); } } set height(value) { if (value > 0) { this._height = value; } else { throw new Error('Height must be positive'); } } get width() { return this._width; } get height() { return this._height; } } const rect = new Rectangle(5, 3); console.log(rect.area); // 15 console.log(rect.perimeter); // 16 rect.width = 10; console.log(rect.area); // 30
Private Fields and Methods
javascriptclass BankAccount { // Private fields (ES2022) #balance = 0; #accountNumber; constructor(accountNumber, initialBalance = 0) { this.#accountNumber = accountNumber; this.#balance = initialBalance; } // Private method #validateAmount(amount) { return amount > 0 && typeof amount === 'number'; } // Public methods deposit(amount) { if (this.#validateAmount(amount)) { this.#balance += amount; return this.#balance; } throw new Error('Invalid amount'); } withdraw(amount) { if (this.#validateAmount(amount) && amount <= this.#balance) { this.#balance -= amount; return this.#balance; } throw new Error('Invalid amount or insufficient funds'); } get balance() { return this.#balance; } get accountInfo() { return `Account: ${this.#accountNumber}, Balance: $${this.#balance}`; } } const account = new BankAccount('12345', 1000); console.log(account.deposit(500)); // 1500 console.log(account.withdraw(200)); // 1300 console.log(account.accountInfo); // Account: 12345, Balance: $1300
Practical Examples
javascript// Task management system class Task { static #idCounter = 0; constructor(title, description = '') { this.id = ++Task.#idCounter; this.title = title; this.description = description; this.completed = false; this.createdAt = new Date(); } complete() { this.completed = true; this.completedAt = new Date(); } toString() { return `[${this.completed ? '✓' : ' '}] ${this.title}`; } } class TaskManager { constructor() { this.tasks = []; } addTask(title, description) { const task = new Task(title, description); this.tasks.push(task); return task; } completeTask(id) { const task = this.tasks.find(t => t.id === id); if (task) { task.complete(); return task; } throw new Error('Task not found'); } getTasks(completed = null) { if (completed === null) return this.tasks; return this.tasks.filter(task => task.completed === completed); } removeTask(id) { const index = this.tasks.findIndex(t => t.id === id); if (index > -1) { return this.tasks.splice(index, 1)[0]; } throw new Error('Task not found'); } } // Usage const taskManager = new TaskManager(); taskManager.addTask('Learn JavaScript', 'Study ES6 classes'); taskManager.addTask('Build a project', 'Create a todo app'); taskManager.completeTask(1); console.log(taskManager.getTasks());
Class Composition
javascript// Mixin pattern for multiple inheritance const Flyable = { fly() { return `${this.name} is flying!`; } }; const Swimmable = { swim() { return `${this.name} is swimming!`; } }; class Bird { constructor(name) { this.name = name; } } class Duck extends Bird { constructor(name) { super(name); // Add mixins Object.assign(this, Flyable, Swimmable); } quack() { return `${this.name} says quack!`; } } const duck = new Duck('Donald'); console.log(duck.fly()); // Donald is flying! console.log(duck.swim()); // Donald is swimming! console.log(duck.quack()); // Donald says quack! // Factory pattern with classes class ShapeFactory { static createShape(type, ...args) { switch (type.toLowerCase()) { case 'circle': return new Circle(...args); case 'rectangle': return new Rectangle(...args); default: throw new Error('Unknown shape type'); } } } class Circle { constructor(radius) { this.radius = radius; } get area() { return Math.PI * this.radius ** 2; } } // Usage const circle = ShapeFactory.createShape('circle', 5); console.log(circle.area); // ~78.54