When One Change Echoes Everywhere: Understanding the Observer Pattern in JavaScript
The observer pattern allows a single source of change to notify multiple subscribers automatically, decoupling the producer from its consumers and enabling flexible, reactive systems.
Thereâs a moment in every application where a single change begins to ripple outward.
A value updates.
And suddenly:
- the UI needs to refresh
- logs need to be recorded
- analytics needs to capture the event
At first, it feels manageable.
You just call everything manually.
updateUI()
updateLog()
updateAnalytics()It works.
Until it doesnât.
The Growing Tension
As your system grows, this pattern becomes fragile.
Every time something changes, you must remember:
Who needs to know?
Who depends on this?
And what happens if you forget one?
The system starts to rely on memoryânot structure.
And thatâs where things begin to break.
A Different Way to Think About Change
The observer pattern introduces a shift.
Instead of asking:
âWho should I call when this changes?â
You begin to ask:
âWho wants to listen to this change?â
That difference is subtle.
But it transforms the system.
From Calling to Notifying
Rather than directly invoking functions, you create a relationship.
Observers subscribe.
The source emits.
const observers = []
function subscribe(fn) {
observers.push(fn)
}
function notify(data) {
observers.forEach(fn => fn(data))
}Now, the source doesnât know who is listening.
It simply announces that something has changed.
Decoupling the System
This is where the pattern becomes powerful.
The source and the observers are no longer tightly connected.
The source doesnât need to know:
- how many observers exist
- what they do
- where they live
It only knows how to notify.
And thatâs enough.
A System That Can Grow
As new features are added, they donât require modifying existing logic.
They simply subscribe.
A new observer appears.
And the system adapts without rewriting its core.
What used to be a chain of direct calls becomes a network of reactions.
This Pattern Is Everywhere
Youâve already seen it.
In the browser:
button.addEventListener("click", handler)In frameworks:
Reactive state updates automatically trigger UI changes.
In event systems:
One action leads to multiple responses.
The observer pattern is not something you add.
Itâs something you recognize.
The Trade-Off
But this flexibility comes with responsibility.
Observers donât disappear automatically.
If you forget to remove them:
- they keep listening
- they keep reacting
- they keep references alive
And over time, this can lead to memory leaks.
The system continues to respondâ
even when it no longer should.
A Different Perspective
Without the observer pattern, change is explicit.
You control every reaction.
With it, change becomes implicit.
You describe relationships, and the system handles the rest.
This makes the system more flexibleâ
but also more dynamic.
A Final Thought
The observer pattern is not about events.
Itâs about how change flows through your system.
It allows one action to echo across multiple partsâ
without those parts needing to know about each other.
And once you adopt that way of thinking,
your code stops being a sequence of instructionsâ
and becomes a system of connections.