What you'll learn
JavaScript objects delegate property lookup through prototype chains. Class syntax offers a familiar, disciplined way to construct objects while preserving that delegation model underneath.
By the end of this lesson, you'll be able to:
- Trace a prototype lookup
- Define classes with instance and static behavior
- Choose composition or inheritance deliberately
Core mental model
Use this decision table as a compact reference. Focus on what each tool means and when it earns its place in production code.
| Concept | What it means | Decision rule |
|---|---|---|
| Prototype chain | Missing properties are searched on linked prototypes | Share methods instead of copying them per object |
| Class | Syntax for constructors and prototype methods | Use when a domain has stable instance identity and invariants |
| Composition | Objects collaborate through contained capabilities | Prefer it when behavior varies independently |
Professional workflow
Build the behavior in small, observable steps. Each step should leave something you can inspect or test.
- Describe the object behavior model boundary: inputs, outputs, state, timing, and expected failures.
- Implement the smallest correct path with names that expose intent.
- Add edge cases and failure handling before introducing abstractions.
- Verify behavior with realistic data and one deliberately adversarial example.
- Refactor only after the observable behavior is protected.
Make behavior observable
Guided code lab
Build an invariant-rich class
Private state can only change through validated public methods.
class BankAccount {
#balance = 0;
constructor(owner) { this.owner = owner; }
deposit(amount) {
if (amount <= 0) throw new RangeError("Amount must be positive");
this.#balance += amount;
}
get balance() { return this.#balance; }
}
const account = new BankAccount("Lina");
account.deposit(50);
console.log(account.owner, account.balance);Delegate through a prototype
Object.create links the new object to shared behavior.
const speaker = { speak() { return this.name + " speaks"; } };
const learner = Object.create(speaker);
learner.name = "Omar";
console.log(learner.speak());
console.log(Object.getPrototypeOf(learner) === speaker);Production practice
Contract
Constructors establish valid instances; public methods preserve their invariants.
Verification
Test own properties, inherited methods, invalid construction, and subclass boundaries.
Operations
Keep inheritance trees shallow and profile only when object volume justifies it.
Common failure mode
Independent workshop
Model subscriptions with a base account and composable billing and notification capabilities.
Your finished workshop must include:
- A class with private state
- At least one shared prototype method
- A written composition-vs-inheritance decision
Definition of done
Recap & quick check
Key takeaways
- Objects delegate through prototypes
- Classes use prototypes underneath
- Private fields protect invariants
- Composition reduces hierarchy coupling
Quick check
1. Where are class methods normally stored?
2. What starts a private field name?
3. What happens after an own-property lookup misses?
Keep the workshop. Later modules deliberately build on these decisions, so each exercise can become part of your final portfolio architecture.