How memory leaks happen and how the Mark-and-Sweep algorithm works.
Timothy was staring at the dashboard he was building. It was getting slow. Sluggish.
"I don't understand," he said. "I am just creating objects. I'm not running heavy calculations. Why is the browser freezing?"
Margaret walked to the chalkboard and drew a large rectangle.
"Because you are running out of space, Timothy. This is the Heap."
The Heap (Memory is Finite)
"The Heap is where JavaScript stores objects, arrays, and functions," Margaret explained. "It is large, but it is not infinite. If you keep allocating memory without freeing it, you exhaust the available space. The browser freezes."
"But I don't free anything," Timothy said. "I just move to the next function."
"You don't have to free memory manually," Margaret corrected. "The Garbage Collector (GC) does it for you. But it follows very strict rules."
Reachability (Mark-and-Sweep)
Margaret drew a small circle at the top of the board and labeled it Root (Window).
"How does the GC know which objects to keep and which to destroy?" she asked.
"It checks if I'm using them?"
"No," Margaret said. "It checks if they are Reachable."
She drew arrows connecting the Root to various objects.
"This is the Mark-and-Sweep algorithm," she said.
-
The Roots: The GC starts at the "Roots" (The Global
windowobject and the current Call Stack). - The References: It follows every reference (every variable, every property). If an object is connected to a Root, it is marked "Safe."
- The Sweep: Any object that cannot be reached from a Root is considered garbage. It is marked for deletion and removed during the next GC cycle.
The Disconnect
Margaret erased a line on the board.
let user = { name: "Timothy" };
// 1. The 'user' variable is a Reference from the Root to the object.
user = null;
// 2. The Reference is broken.
"When you set user = null," Margaret explained, "you didn't delete the object. You just broke the Reference."
"So the object is stranded?" Timothy asked.
"Exactly. The next time the GC runs, it will start at the Root, try to find that object, and fail. Since it is unreachable, the space is reclaimed."
The Memory Leak
Timothy looked at his slow code. "So if my app is slow, it means I am holding onto objects I don't need?"
"Yes," Margaret said. "You have a Memory Leak. You are accidentally keeping a Reference alive."
She wrote a common trap on the board:
function startDashboard() {
const hugeData = new Array(100000).fill("Data");
// The Trap:
window.addEventListener('resize', () => {
console.log(hugeData.length);
});
}
"Trace the References," Margaret commanded.
Timothy looked at the diagram.
-
The Root (Window) has an Event Listener attached to it (
resize). -
The Listener is a function that uses
hugeData. - Because of Closure, the Listener must hold a reference to
hugeData.
"I see it," Timothy realized. "The Window holds the Listener. The Listener holds the Data."
"Correct," Margaret said. "Even if startDashboard finishes running, that connection remains. The GC sees a clear path from the Root to your massive array. It cannot delete it."
The Solution
"How do I fix it?" Timothy asked.
"You must break the reference," Margaret said.
She added the cleanup code:
window.removeEventListener('resize', myListener);
"Remove the listener," she said. "The connection breaks. The huge data becomes unreachable. The Garbage Collector sweeps it away, and your browser breathes again."
The Conclusion
"Memory management isn't about micromanaging every object," Margaret concluded, wiping the chalk dust from her hands. "It's about understanding the invisible connections that keep data alive. Break the connections you don't need, and let the garbage collector do its job."
Aaron Rose is a software engineer and technology writer at tech-reader.blog and the author of Think Like a Genius.
Top comments (2)
Hi, thanks for this post.
I really like your explaining interesting concepts in stories.
in a world where the RAMs are more abundant and cheaper, and since web devs work on laptops/servers not chips, a typical JS developer may easily be inclined to not-think about memory management -true, it is not as C++ development in the end- but i suppose it can affect web performance for certain cases.
I suppose event handlers are the easiest trap, as you defined. In react, as they are mostly defined in useEffects, it must be cared and removed during the unmounting of the component, which is something that can be forgotten in haste (speaking from experience)
❤💯🙏