JavaScript Lesson 20: Advanced JavaScript
You have built a strong JavaScript foundation. This final lesson covers the patterns that separate beginner code from professional code: classes, closures, and error handling.
ES6 Classes
class Animal {
#name; // private field (ES2022)
constructor(name, sound) {
this.#name = name;
this.sound = sound;
}
speak() {
return `${this.#name} says ${this.sound}!`;
}
get name() { return this.#name; } // getter
set name(val) { this.#name = val; } // setter
}
class Dog extends Animal {
constructor(name) {
super(name, "Woof");
this.tricks = [];
}
learn(trick) {
this.tricks.push(trick);
}
}
const dog = new Dog("Rex");
dog.learn("sit");
console.log(dog.speak()); // Rex says Woof!
console.log(dog.tricks); // ["sit"]
Closures
// A closure gives a function access to its outer scope
function makeCounter() {
let count = 0; // private — cannot be accessed from outside!
return {
increment() { count++; },
decrement() { count--; },
getCount() { return count; }
};
}
const counter = makeCounter();
counter.increment();
counter.increment();
counter.increment();
console.log(counter.getCount()); // 3
// console.log(count); // ReferenceError! Private!
Error Handling
class ValidationError extends Error {
constructor(message, field) {
super(message);
this.name = "ValidationError";
this.field = field;
}
}
function validateEmail(email) {
if (!email.includes("@")) {
throw new ValidationError("Invalid email format", "email");
}
return true;
}
try {
validateEmail("not-an-email");
} catch (err) {
if (err instanceof ValidationError) {
console.error(`Field: ${err.field} — ${err.message}`);
} else {
throw err; // re-throw unexpected errors
}
}
You completed the JavaScript course!
What to learn next:
- React — Build complex UIs with components
- Node.js — Run JavaScript on the server
- TypeScript — Add types to JavaScript
🏋️ Practice Task
Build a Todo class with: private _items array, add(text) method, remove(id) method, complete(id) method, and list() method that returns formatted items. Each item should have id, text, completed, and createdAt fields.
💡 Hint: Use a static counter for IDs: static #nextId = 1. In add(): this._items.push({id: Todo.#nextId++, text, completed: false, createdAt: new Date()})