Lesson 2 of 6 · 10 min · 1 hands-on step
Encapsulation: Protecting Your Data
Hide internals behind a clear interface so nobody can put an object into a broken state.
The problem
const account = { balance: 100 };
account.balance = -9999; // nothing stops this!
console.log(account.balance);Any code, anywhere, can break the rules. In a big codebase you'd never know who did it.
The fix: hide data, expose behavior
Encapsulation means an object keeps its data private and offers methods as the only way to change it. The methods enforce the rules.
class Thermostat {
#target = 20; // private: only code inside this class can touch it
get target() {
return this.#target;
}
set target(value) {
if (value < 10 || value > 30) throw new Error("Keep it between 10 and 30°C");
this.#target = value;
}
}
const t = new Thermostat();
t.target = 24;
console.log(t.target);
try {
t.target = 99;
} catch (e) {
console.log("Rejected:", e.message);
}Interface vs implementation
The interface is what other code can use (deposit, withdraw, balance). The implementation is how it works inside. Keep the interface small and stable, and you can change the inside freely without breaking anyone.
In Python, the convention is a leading underscore (
self._balance) meaning "private, please don't touch". JavaScript's#makes it truly private.
🧪 Practice
Use a private field #balance so the balance can't be changed directly. Provide:
deposit(amount): throws anErrorif amount is not positivewithdraw(amount): throws anErrorif there isn't enough money- a getter
balancethat returns the current balance (read-only)
class Account {
constructor(opening = 0) {
this.balance = opening; // anyone can change this!
}
}
Output appears here. Press Run or Ctrl/⌘ + Enter.
✅ Check your understanding
What's the main benefit of encapsulation?
Create a free account to track your progress.