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

JavaScript · try it
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.

JavaScript · try it
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 an Error if amount is not positive
  • withdraw(amount): throws an Error if there isn't enough money
  • a getter balance that returns the current balance (read-only)
JavaScript
class Account {
  constructor(opening = 0) {
    this.balance = opening; // anyone can change this!
  }
}

Output appears here. Press Run or Ctrl/⌘ + Enter.

✅ Check your understanding

  1. What's the main benefit of encapsulation?

Create a free account to track your progress.